org.rythmengine.RythmEngine - java examples

Here are the examples of the java api org.rythmengine.RythmEngine taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

65 Examples 7

19 View Complete Implementation : RythmTemplate.java
Copyright Apache License 2.0
Author : actframework
public clreplaced RythmTemplate extends TemplateBase {

    private RythmEngine engine;

    private String literal;

    private boolean inline;

    public RythmTemplate(RythmEngine engine, String literal) {
        this(engine, literal, false);
    }

    public RythmTemplate(RythmEngine engine, String literal, boolean inline) {
        this.engine = $.requireNotNull(engine);
        this.literal = literal;
        this.inline = inline;
    }

    @Override
    protected void beforeRender(ActionContext context) {
        Locale locale = context.locale();
        engine = engine.prepare(locale);
    }

    @Override
    protected void beforeRender(MailerContext context) {
        Locale locale = context.locale(true);
        engine = engine.prepare(locale);
    }

    @Override
    protected String render(Map<String, Object> renderArgs) {
        // TODO handle render exception
        ITemplate t = template(renderArgs);
        return t.render();
    }

    private org.rythmengine.template.ITemplate template(Map<String, Object> renderArgs) {
        if (inline) {
            TemplateClreplacedManager tcm = engine.clreplacedes();
            TemplateClreplaced tc = tcm.getByTemplate(literal);
            if (null == tc) {
                tc = new TemplateClreplaced(literal, engine, BasicRythm.INSTANCE);
            }
            ITemplate t = tc.asTemplate(engine);
            t.__setRenderArgs(renderArgs);
            return t;
        } else {
            return engine.getTemplate(literal, renderArgs);
        }
    }

    public static RythmTemplate find(RythmEngine engine, String path) {
        ITemplateResource resource = engine.resourceManager().getResource(path);
        if (!resource.isValid()) {
            return null;
        } else {
            return new RythmTemplate(engine, path);
        }
    }
}

19 View Complete Implementation : TemplateClassLoader.java
Copyright Apache License 2.0
Author : rythmengine
private static ClreplacedLoader getDefParent(RythmEngine engine) {
    return engine.conf().get(RythmConfigurationKey.ENGINE_CLreplaced_LOADER_PARENT_IMPL);
}

19 View Complete Implementation : RythmPlugin.java
Copyright Apache License 2.0
Author : rythmengine
public clreplaced RythmPlugin extends PlayPlugin {

    public static final String VERSION = "1.0-b10";

    public static final String R_VIEW_ROOT = "app/rythm";

    public static void info(String msg, Object... args) {
        Logger.info(msg_(msg, args));
    }

    public static void info(Throwable t, String msg, Object... args) {
        Logger.info(t, msg_(msg, args));
    }

    public static void debug(String msg, Object... args) {
        Logger.debug(msg_(msg, args));
    }

    public static void debug(Throwable t, String msg, Object... args) {
        Logger.debug(t, msg_(msg, args));
    }

    public static void trace(String msg, Object... args) {
        Logger.trace(msg_(msg, args));
    }

    public static void trace(Throwable t, String msg, Object... args) {
        Logger.warn(t, msg_(msg, args));
    }

    public static void warn(String msg, Object... args) {
        Logger.warn(msg_(msg, args));
    }

    public static void warn(Throwable t, String msg, Object... args) {
        Logger.warn(t, msg_(msg, args));
    }

    public static void error(String msg, Object... args) {
        Logger.error(msg_(msg, args));
    }

    public static void error(Throwable t, String msg, Object... args) {
        Logger.error(t, msg_(msg, args));
    }

    public static void fatal(String msg, Object... args) {
        Logger.fatal(msg_(msg, args));
    }

    public static void fatal(Throwable t, String msg, Object... args) {
        Logger.fatal(t, msg_(msg, args));
    }

    private static String msg_(String msg, Object... args) {
        return String.format("RythmPlugin-" + VERSION + "> %1$s", String.format(msg, args));
    }

    public static RythmEngine engine;

    public static boolean underscoreImplicitVariableName = false;

    public static boolean refreshOnRender = true;

    public static String templateRoot = R_VIEW_ROOT;

    public static boolean enableCodeMarker = false;

    public static String jquery = "http://code.jquery.com/jquery-1.9.1.min.js";

    public static boolean fontawesome = false;

    // public static String templateRoot2 = R_VIEW_ROOT;
    // public static String tagRoot = "app/views/tags/rythm";
    public static List<ImplicitVariables.Var> implicitRenderArgs = new ArrayList<ImplicitVariables.Var>();

    public static VirtualFileTemplateResourceLoader resourceLoader;

    public static void registerImplicitRenderArg(final String name, final String type) {
        implicitRenderArgs.add(new ImplicitVariables.Var(name, type) {

            @Override
            protected Object evaluate() {
                return Scope.RenderArgs.current().get(name());
            }
        });
    }

    public static void loadTemplatePaths() {
        for (VirtualFile mroot : Play.modules.values()) {
            VirtualFile mviews = mroot.child(R_VIEW_ROOT);
            if (mviews.exists()) {
                Play.templatesPath.add(0, mviews);
            }
        }
        VirtualFile rythm = VirtualFile.open(Play.applicationPath).child(R_VIEW_ROOT);
        if (rythm.exists()) {
            Play.templatesPath.add(0, rythm);
        }
    }

    private boolean loadingRoute = false;

    public static boolean precompiling() {
        return System.getProperty("precompile") != null;
    }

    @Override
    public void onLoad() {
        if (null != engine) {
            engine.shutdown();
        }
        loadTemplatePaths();
        StaticRouteResolver.loadStaticRoutes();
        if (!precompiling()) {
            Play.lazyLoadTemplates = true;
        }
    }

    private boolean logActionInvocationTime;

    private ApplicationClreplacedloader playAppClreplacedLoader = new ApplicationClreplacedloader() {

        private ApplicationClreplacedloader pcl() {
            return Play.clreplacedloader;
        }

        @Override
        public Clreplaced<?> loadClreplaced(String name) throws ClreplacedNotFoundException {
            return pcl().loadClreplaced(name);
        }

        @Override
        public URL getResource(String name) {
            if (name.endsWith(".clreplaced")) {
                String base;
                if (Play.usePrecompiled) {
                    base = "precompiled";
                } else {
                    base = "tmp";
                }
                File file = new File(Play.applicationPath, base + "/java/" + name);
                if (file.exists() && file.canRead()) {
                    try {
                        return file.toURI().toURL();
                    } catch (MalformedURLException e) {
                        throw new UnexpectedException(e);
                    }
                }
                return pcl().getParent().getResource(name);
            } else {
                return pcl().getResource(name);
            }
        }

        @Override
        public Enumeration<URL> getResources(String name) throws IOException {
            return pcl().getResources(name);
        }

        @Override
        public InputStream getResourcereplacedtream(String name) {
            return pcl().getResourcereplacedtream(name);
        }

        public Clreplaced<?> loadApplicationClreplaced(String name) {
            try {
                return pcl().loadApplicationClreplaced(name);
            } catch (SecurityException se) {
                return null;
            } catch (RythmException re) {
                if (re.getCause() instanceof SecurityException) {
                    return null;
                }
                throw re;
            }
        }
    };

    @Override
    public void onConfigurationRead() {
        // already configured
        if (null != engine && Play.mode.isProd())
            return;
        if (null != engine && preloadConf && Play.mode.isDev()) {
            // the following load conf are caused by app restart at dev mode
            preloadConf = false;
            return;
        }
        Properties playConf = Play.configuration;
        // workaround for https://play.lighthouseapp.com/projects/57987-play-framework/tickets/1614-calling-to-plugins-beforeactioninvocation-and-afteractioninvocation-should-be-symmetric
        logActionInvocationTime = Boolean.parseBoolean(Play.configuration.getProperty("betterlogs.trace.actionInvocation.time", Play.mode.isDev() ? "true" : "false"));
        // eof workaround for https://play.lighthouseapp.com/projects/57987-play-framework/tickets/1614-calling-to-plugins-beforeactioninvocation-and-afteractioninvocation-should-be-symmetric
        // special configurations
        underscoreImplicitVariableName = Boolean.parseBoolean(playConf.getProperty("rythm.implicitVariable.underscore", "false"));
        refreshOnRender = Boolean.parseBoolean(playConf.getProperty("rythm.resource.refreshOnRender", "true"));
        enableCodeMarker = Play.mode.isDev() && Boolean.parseBoolean(playConf.getProperty("rythm.enableCodeMarker", "false"));
        jquery = playConf.getProperty("rythm.jquery", "http://code.jquery.com/jquery-1.9.1.min.js");
        fontawesome = Boolean.parseBoolean(playConf.getProperty("rythm.fontawesome", "false"));
        Properties p = new Properties();
        // set default configurations
        // p.put("rythm.root", new File(Play.applicationPath, "app/views"));
        // p.put("rythm.tag.root", new File(Play.applicationPath, tagRoot));
        final boolean isProd = Play.mode.isProd();
        p.put("rythm.engine.mode", isProd ? Rythm.Mode.prod : Rythm.Mode.dev);
        p.put("rythm.engine.plugin.version", VERSION);
        p.put("rythm.codegen.compact.enabled", isProd);
        p.put("rythm.engine.clreplaced_loader.parent", playAppClreplacedLoader);
        p.put("rythm.engine.load_precompiled.enabled", Play.usePrecompiled);
        p.put("rythm.log.source.template.enabled", true);
        p.put("rythm.log.source.java.enabled", true);
        p.put("rythm.engine.precompile_mode.enabled", Play.mode.isProd() && System.getProperty("precompile") != null);
        if (Play.usePrecompiled || Play.getFile("precompiled").exists()) {
            File preCompiledRoot = new File(Play.getFile("precompiled"), "rythm");
            if (!preCompiledRoot.exists())
                preCompiledRoot.mkdirs();
            p.put("rythm.home.precompiled", preCompiledRoot);
        }
        resourceLoader = new VirtualFileTemplateResourceLoader();
        p.put("rythm.resource.loader.impls", resourceLoader);
        p.put("rythm.resource.loader.def.enabled", false);
        p.put("rythm.resource.name.suffix", "");
        p.put("rythm.engine.clreplaced_loader.byte_code_helper", new IByteCodeHelper() {

            @Override
            public byte[] findByteCode(String typeName) {
                ApplicationClreplacedes clreplacedBag = Play.clreplacedes;
                if (clreplacedBag.hasClreplaced(typeName)) {
                    ApplicationClreplacedes.ApplicationClreplaced applicationClreplaced = clreplacedBag.getApplicationClreplaced(typeName);
                    return applicationClreplaced.enhancedByteCode;
                } else {
                    return null;
                }
            }
        });
        p.put("rythm.log.factory", new ILoggerFactory() {

            @Override
            public ILogger getLogger(Clreplaced<?> clazz) {
                return PlayRythmLogger.instance;
            }
        });
        // enable java extension by default
        p.put("rythm.feature.transformer.enabled", true);
        p.put("rythm.cache.prod_only", "true");
        p.put("rythm.default.cache_ttl", 60 * 60);
        p.put("rythm.cache.service", new ICacheService() {

            private int defaultTTL = 60 * 60;

            @Override
            public void startup() {
            }

            @Override
            public void put(String key, Serializable value, int ttl) {
                Cache.cacheImpl.set(key, value, ttl);
            }

            @Override
            public void put(String key, Serializable value) {
                Cache.cacheImpl.set(key, value, defaultTTL);
            }

            @Override
            public Serializable remove(String key) {
                Object o = Cache.get(key);
                Cache.delete(key);
                return null == o ? null : (o instanceof Serializable ? (Serializable) o : o.toString());
            }

            @Override
            public void evict(String key) {
                Cache.delete(key);
            }

            @Override
            public Serializable get(String key) {
                Object o = Cache.get(key);
                return null == o ? null : (o instanceof Serializable ? (Serializable) o : o.toString());
            }

            @Override
            public boolean contains(String key) {
                Object o = Cache.get(key);
                return null != o;
            }

            @Override
            public void clear() {
                try {
                    Cache.clear();
                } catch (Throwable e) {
                // ignore it
                }
            }

            @Override
            public void setDefaultTTL(int ttl) {
                defaultTTL = ttl;
            }

            @Override
            public void shutdown() {
                clear();
            }
        });
        // set user configurations - coming from application.conf
        for (String key : playConf.stringPropertyNames()) {
            if (key.startsWith("rythm.")) {
                p.setProperty(key, playConf.getProperty(key));
            }
        }
        debug("User defined rythm properties configured");
        // restricted clreplaced in sandbox mode
        String appRestricted = p.getProperty("rythm.sandbox.restricted_clreplacedes", "");
        appRestricted += ";play.Play;play.clreplacedloading;play.server";
        p.setProperty("rythm.sandbox.restricted_clreplacedes", appRestricted);
        // set template root
        templateRoot = p.getProperty("rythm.home.template", templateRoot);
        p.put("rythm.home.template", new File(Play.applicationPath, templateRoot));
        if (Logger.isDebugEnabled())
            debug("rythm template root set to: %s", p.get("rythm.home.template"));
        // // set tag root
        // tagRoot = p.getProperty("rythm.tag.root", tagRoot);
        // if (tagRoot.endsWith("/")) tagRoot = tagRoot.substring(0, tagRoot.length() - 1);
        // p.put("rythm.tag.root", new File(Play.applicationPath, tagRoot));
        // if (Logger.isDebugEnabled()) debug("rythm tag root set to %s", p.get("rythm.tag.root"));
        // set tmp dir
        debug("Play standalone play server? %s", Play.standalonePlayServer);
        // boolean isGaePresent = Boolean.valueOf(p.getProperty("rythm.gae", "false")) ;
        boolean isGaePresent = isGaeSdkInClreplacedpath();
        if (isGaePresent) {
            warn("GAE SDK present in the clreplacedpath");
        }
        boolean gae = !Play.standalonePlayServer && isGaePresent;
        boolean readOnly = gae || Boolean.valueOf(p.getProperty("rythm.engine.file_write", "false"));
        if (!readOnly) {
            File tmpDir = new File(Play.tmpDir, "rythm");
            tmpDir.mkdirs();
            p.put("rythm.home.tmp", tmpDir);
            if (Logger.isDebugEnabled()) {
                debug("rythm tmp dir set to %s", p.get("rythm.home.tmp"));
            }
        } else if (gae) {
            warn("GAE enabled");
        }
        p.put("rythm.engine.mode", Play.mode.isDev() && Play.standalonePlayServer ? Rythm.Mode.dev : Rythm.Mode.prod);
        p.put("rythm.engine.playframework", true);
        p.put("rythm.render.listener", new IRythmListener.ListenerAdaptor() {

            @Override
            public void onInvoke(ITag tag) {
                RythmTagContext.enterTag(tag.__getName());
            }

            @Override
            public void invoked(ITag tag) {
                RythmTagContext.exitTag();
            }
        });
        final TemplatePropertiesEnhancer templateEnhancer = new TemplatePropertiesEnhancer();
        p.put("rythm.codegen.byte_code_enhancer", new IByteCodeEnhancer() {

            @Override
            public byte[] enhance(String clreplacedName, byte[] clreplacedBytes) throws Exception {
                if (engine.conf().disableFileWrite())
                    return clreplacedBytes;
                ApplicationClreplacedes.ApplicationClreplaced applicationClreplaced = new ApplicationClreplacedes.ApplicationClreplaced();
                applicationClreplaced.javaByteCode = clreplacedBytes;
                applicationClreplaced.enhancedByteCode = clreplacedBytes;
                File f = File.createTempFile("rythm_", clreplacedName.contains("$") ? "$1" : "" + ".java", Play.tmpDir);
                applicationClreplaced.javaFile = VirtualFile.open(f);
                try {
                    templateEnhancer.enhanceThisClreplaced(applicationClreplaced);
                } catch (Exception e) {
                    error(e, "Error enhancing clreplaced: %s", clreplacedName);
                }
                if (!f.delete())
                    f.deleteOnExit();
                return applicationClreplaced.enhancedByteCode;
            }
        });
        p.put("rythm.codegen.source_code_enhancer", new ISourceCodeEnhancer() {

            @Override
            public List<String> imports() {
                List<String> l = new ArrayList(Arrays.asList(TemplateClreplacedAppEnhancer.imports().split("[,\n]+")));
                l.add(JavaExtensions.clreplaced.getName());
                l.add("models.*");
                l.add("controllers.*");
                return l;
            }

            @Override
            public String sourceCode() {
                String prop = "\n\tprotected <T> T _getBeanProperty(Object o, String prop) {" + "\n\t\treturn (T)org.rythmengine.play.utils.JavaHelper.getProperty(o, prop);" + "\n\t}\n" + "\n\tprotected void _setBeanProperty(Object o, String prop, Object val) {" + "\n\t\torg.rythmengine.play.utils.JavaHelper.setProperty(o, prop, val);" + "\n\t}\n" + "\n\tprotected boolean _hasBeanProperty(Object o, String prop) {" + "\n\t\treturn org.rythmengine.play.utils.JavaHelper.hasProperty(o, prop);" + "\n\t}\n";
                String url = "\n    protected play.mvc.Router.ActionDefinition _act(String action, Object... params) {return _act(false, action, params);}" + "\n    protected play.mvc.Router.ActionDefinition _act(boolean isAbsolute, String action, Object... params) {" + "\n        org.rythmengine.internal.compiler.TemplateClreplaced tc = __getTemplateClreplaced(true);" + "\n        boolean escapeXML = (!tc.isStringTemplate() && tc.templateResource.getKey().toString().endsWith(\".xml\"));" + "\n        return new org.rythmengine.play.utils.ActionBridge(isAbsolute, escapeXML).invokeMethod(action, params);" + "\n   }\n" + "\n    protected String _url(String action, Object... params) {return _url(false, action, params);}" + "\n    protected String _url(boolean isAbsolute, String action, Object... params) { return _act(isAbsolute, action, params).toString();" + "\n   }\n";
                String msg = "\n    protected String _msg(String key, Object ... params) {return play.i18n.Messages.get(key, params);}";
                // add String _url(String) method to template clreplaced
                return prop + msg + url + TemplateClreplacedAppEnhancer.sourceCode();
            }

            @Override
            public Map<String, ?> getRenderArgDescriptions() {
                Map<String, Object> m = new HashMap<String, Object>();
                // App registered render args
                for (ImplicitVariables.Var var : implicitRenderArgs) {
                    m.put(var.name(), var.type);
                }
                // Play default render args
                for (ImplicitVariables.Var var : ImplicitVariables.vars) {
                    m.put(var.name(), var.type);
                }
                return m;
            }

            @Override
            public void setRenderArgs(ITemplate template) {
                Map<String, Object> m = new HashMap<String, Object>();
                for (ImplicitVariables.Var var : ImplicitVariables.vars) {
                    m.put(var.name(), var.evaluate());
                }
                template.__setRenderArgs(m);
            }
        });
        p.put("rythm.render.exception_handler", new IRenderExceptionHandler() {

            @Override
            public boolean handleTemplateExecutionException(Exception e, TemplateBase template) {
                boolean handled = false;
                if (e instanceof RenderTemplate) {
                    template.p(((RenderTemplate) e).getContent());
                } else if (e instanceof RenderHtml || e instanceof RenderJson || e instanceof RenderStatic || e instanceof RenderXml || e instanceof RenderText) {
                    Http.Response resp = new Http.Response();
                    resp.out = new ByteArrayOutputStream();
                    ((Result) e).apply(null, resp);
                    try {
                        template.p(resp.out.toString("utf-8"));
                    } catch (UnsupportedEncodingException e0) {
                        throw new UnexpectedException("utf-8 not supported?");
                    }
                }
                if (handled) {
                    // allow next controller action call
                    ControllersEnhancer.ControllerInstrumentation.initActionCall();
                    resetActionCallFlag();
                    return true;
                }
                return false;
            }
        });
        p.put("rythm.i18n.message.resolver", new PlayI18nMessageResolver());
        p.put("rythm.resource.autoScan", false);
        if (null != engine) {
            engine.shutdown();
        }
        engine = new RythmEngine(p);
        // Rythm.engine.cacheService.shutdown();
        // /Rythm.init(engine);
        IParserFactory[] factories = { new AbsoluteUrlReverseLookupParser(), new UrlReverseLookupParser(), new MessageLookupParser(), new GroovyVerbatimTagParser(), new ExitIfNoModuleParser() };
        engine.extensionManager().registerUserDefinedParsers(factories).registerUserDefinedParsers(SimpleRythm.ID, factories).registerExpressionProcessor(new ActionInvokeProcessor());
        debug("Play specific parser registered");
        FastTagBridge.registerFastTags(engine);
        registerJavaTags(engine);
        ActionTagBridge.registerActionTags(engine);
        if (engine.conf().transformEnabled()) {
            JavaExtensionBridge.registerPlayBuiltInJavaExtensions(engine);
            JavaExtensionBridge.registerAppJavaExtensions(engine);
        }
        RythmTemplateLoader.clear();
    // if (engine.conf().gae()) {
    // TemplateLoader.getAllTemplate();
    // }
    }

    public static boolean isGaeSdkInClreplacedpath() {
        try {
            String clreplacedname = "com.google.appengine.api.LifecycleManager";
            Clreplaced clazz = Clreplaced.forName(clreplacedname);
            return clazz != null;
        } catch (Throwable t) {
        // Nothing to do
        }
        return false;
    }

    public static final String ACTION_CALL_FLAG_KEY = "__RYTHM_PLUGIN_ACTION_CALL_";

    public static void resetActionCallFlag() {
        Stack<Boolean> actionCalls = Scope.RenderArgs.current().get(ACTION_CALL_FLAG_KEY, Stack.clreplaced);
        if (null != actionCalls) {
            actionCalls.pop();
        }
    }

    public static void setActionCallFlag() {
        Scope.RenderArgs renderAargs = Scope.RenderArgs.current();
        Stack<Boolean> actionCalls = renderAargs.get(ACTION_CALL_FLAG_KEY, Stack.clreplaced);
        if (null == actionCalls) {
            actionCalls = new Stack<Boolean>();
            renderAargs.put(ACTION_CALL_FLAG_KEY, actionCalls);
        }
        actionCalls.push(true);
    }

    public static boolean isActionCall() {
        Scope.RenderArgs renderArgs = Scope.RenderArgs.current();
        if (null == renderArgs) {
            // calling from Mails?
            return false;
        }
        Stack<Boolean> actionCalls = Scope.RenderArgs.current().get(ACTION_CALL_FLAG_KEY, Stack.clreplaced);
        if (null == actionCalls || actionCalls.empty())
            return false;
        return true;
    }

    @Override
    public void afterApplicationStart() {
    // if (engine.mode().isProd() && engine.conf().loadPrecompiled()) {
    // // pre load template clreplacedes if they are not loaded yet
    // VirtualFile vf = Play.getVirtualFile("app/rythm/welcome.html");
    // String key = vf.relativePath().replaceFirst("\\{.*?\\}", "");
    // if (!engine.clreplacedes().tmplIdx.containsKey(key)) {
    // RythmTemplateLoader.scanRythmFolder();
    // }
    // } else {
    // //RythmTemplateLoader.scanRythmFolder();
    // }
    }

    private void registerJavaTags(RythmEngine engine) {
        long l = System.currentTimeMillis();
        // -- register application java tags
        List<ApplicationClreplacedes.ApplicationClreplaced> clreplacedes = Play.clreplacedes.getreplacedignableClreplacedes(FastRythmTag.clreplaced);
        for (ApplicationClreplacedes.ApplicationClreplaced ac : clreplacedes) {
            registerJavaTag(ac.javaClreplaced, engine);
        }
        // -- register PlayRythm build-in tags
        Clreplaced<?>[] ca = FastRythmTags.clreplaced.getDeclaredClreplacedes();
        for (Clreplaced<?> c : ca) {
            registerJavaTag(c, engine);
        }
        debug("%sms to register rythm java tags", System.currentTimeMillis() - l);
    }

    private void registerJavaTag(Clreplaced<?> jc, RythmEngine engine) {
        int flag = jc.getModifiers();
        if (Modifier.isAbstract(flag))
            return;
        try {
            Constructor<?> c = jc.getConstructor(new Clreplaced[] {});
            c.setAccessible(true);
            FastRythmTag tag = (FastRythmTag) c.newInstance();
            engine.registerTemplate(tag);
        } catch (Exception e) {
            throw new UnexpectedException("Error initialize JavaTag: " + jc.getName(), e);
        }
    }

    public static final Template VOID_TEMPLATE = new Template() {

        @Override
        public void compile() {
        // 
        }

        @Override
        protected String internalRender(Map<String, Object> args) {
            throw new UnexpectedException("It's not supposed to be called");
        }
    };

    private boolean preloadConf = false;

    @Override
    public Template loadTemplate(VirtualFile file) {
        if (loadingRoute)
            return null;
        if (null == engine) {
            preloadConf = true;
            // in prod mode this method is called in preCompile() when onConfigurationRead() has not been called yet
            onConfigurationRead();
            StaticRouteResolver.processVersionedRoutes();
        }
        // warn(">>>> %s", file.relativePath());
        if (precompiling()) {
            try {
                return RythmTemplateLoader.loadTemplate(file);
            } catch (Throwable e) {
                error(e, "Error precompiling template: %s", file);
                return null;
            }
        } else {
            return RythmTemplateLoader.loadTemplate(file);
        }
    }

    @Override
    public void detectChange() {
        if (!refreshOnRender)
            engine.clreplacedLoader().detectChanges();
    }

    private Map<Clreplaced<? extends ICacheKeyProvider>, ICacheKeyProvider> keyProviders = new HashMap<Clreplaced<? extends ICacheKeyProvider>, ICacheKeyProvider>();

    @Override
    public void beforeActionInvocation(Method actionMethod) {
        TagContext.init();
        if (Play.mode.isDev() && Boolean.valueOf(Play.configuration.getProperty("rythm.cache.prodOnly", "true"))) {
            return;
        }
        Http.Request request = Http.Request.current();
        Cache4 cache4 = actionMethod.getAnnotation(Cache4.clreplaced);
        if (null == cache4) {
            return;
        }
        if (logActionInvocationTime) {
            Logger.info("");
            Logger.info("[BL]>>>>>>> [%s]", Http.Request.current().action);
            Http.Request.current().args.put("__BL_COUNTER__", System.currentTimeMillis());
        }
        String m = request.method;
        if ("GET".equals(m) || "HEAD".equals(m) || (cache4.cachePost() && "POST".equals(m))) {
            String cacheKey = cache4.id();
            boolean sessSensitive = cache4.sessionSensitive();
            if (!sessSensitive) {
                sessSensitive = cache4.useSessionData();
            }
            boolean schemeSensitive = cache4.schemeSensitive();
            boolean langSensitive = cache4.langSensitive();
            if (S.isEmpty(cacheKey)) {
                Clreplaced<? extends ICacheKeyProvider> kpFact = cache4.key();
                try {
                    ICacheKeyProvider keyProvider = keyProviders.get(kpFact);
                    if (null == keyProvider) {
                        keyProvider = kpFact.newInstance();
                        keyProviders.put(kpFact, keyProvider);
                    }
                    cacheKey = keyProvider.getKey(sessSensitive, schemeSensitive, langSensitive);
                    if (S.isEmpty(cacheKey)) {
                        // warn("empty cache key found");
                        return;
                    }
                } catch (Exception e) {
                    error(e, "error get key from key provider");
                    return;
                }
            // Note we cannot do any transform on user supplied key
            // as it might be used to deprecate cache. So we will leave
            // the cache key provider to handle session and scheme
            // if (cache4.useSessionData()) {
            // cacheKey = cacheKey + Scope.Session.current().toString();
            // }
            // if (cache4.schemeSensitive()) cacheKey += request.secure;
            } else {
                if (sessSensitive) {
                    cacheKey = cacheKey + Scope.Session.current().toString();
                }
                if (schemeSensitive) {
                    cacheKey += request.secure;
                }
                if (langSensitive) {
                    cacheKey += Lang.get();
                }
            }
            request.args.put("rythm-urlcache-key", cacheKey);
            request.args.put("rythm-urlcache-actionMethod", actionMethod);
            Result result = (Result) play.cache.Cache.get(cacheKey);
            if (null == result)
                return;
            if (!(result instanceof Cache4.CacheResult)) {
                result = new Cache4.CacheResult(cacheKey, result);
            }
            throw result;
        }
    }

    @Override
    public void onActionInvocationResult(Result result) {
        if (result instanceof Cache4.CacheResult) {
            // it's already a cached result
            return;
        }
        if (result instanceof Redirect) {
            Redirect r = (Redirect) result;
            if (r.code != Http.StatusCode.MOVED) {
                // not permanent redirect, don't cache it
                return;
            }
        }
        if (result instanceof NotFound || result instanceof play.mvc.results.Error) {
            // might recover later, so don't cache it
            return;
        }
        Object o = Http.Request.current().args.get("rythm-urlcache-key");
        if (null == o)
            return;
        String cacheKey = o.toString();
        Method actionMethod = (Method) Http.Request.current().args.get("rythm-urlcache-actionMethod");
        String duration = actionMethod.getAnnotation(Cache4.clreplaced).value();
        if (S.isEmpty(duration))
            duration = "1h";
        if (duration.startsWith("cron.")) {
            duration = Play.configuration.getProperty(duration, "1h");
        }
        if ("forever".equals(duration)) {
            duration = "99999d";
        }
        play.cache.Cache.set(cacheKey, new Cache4.CacheResult(cacheKey, result), duration);
    }

    @Override
    public String getMessage(String locale, Object key, Object... args) {
        String value = null;
        if (key == null) {
            return "";
        }
        Map<String, Properties> locales = Messages.locales;
        String k = key.toString();
        if (locales.containsKey(locale)) {
            value = locales.get(locale).getProperty(k);
        }
        if (value == null) {
            int pos = locale.indexOf('_');
            if (pos > -1) {
                locale = locale.substring(0, pos);
                value = locales.get(locale).getProperty(k);
            }
            if (value == null) {
                value = Messages.defaults.getProperty(key.toString());
            }
        }
        if (value == null) {
            value = key.toString();
        }
        return Messages.formatString(value, args);
    }

    private static RythmEngine engine() {
        return engine;
    }

    // ----- render interfaces ---------
    /**
     * @param template
     * @param args
     * @return render result
     * @see RythmEngine#render(String, Object...)
     */
    public static String render(String template, Object... args) {
        return engine().render(template, args);
    }

    /**
     * @param file
     * @param args
     * @return render result
     * @see RythmEngine#render(java.io.File, Object...)
     */
    public static String render(File file, Object... args) {
        return engine().render(file, args);
    }

    public static String render(VirtualFile file, Object... args) {
        return engine().render(file.getRealFile(), args);
    }

    /**
     * @param template
     * @param args
     * @return render result
     * @see RythmEngine#subsreplacedute(String, Object...)
     */
    public static String subsreplacedute(String template, Object... args) {
        return engine().subsreplacedute(template, args);
    }

    /**
     * @param template
     * @param args
     * @return render result
     * @see RythmEngine#subsreplacedute(java.io.File, Object...)
     */
    public static String subsreplacedute(File template, Object... args) {
        return engine().subsreplacedute(template, args);
    }

    /**
     * @param template
     * @param obj
     * @return render result
     * @see RythmEngine#toString(String, Object)
     */
    public static String toString(String template, Object obj) {
        return engine().toString(template, obj);
    }

    /**
     * @param obj
     * @return render result
     * @see RythmEngine#toString(Object)
     */
    public static String toString(Object obj) {
        return engine().toString(obj);
    }

    /**
     * @param obj
     * @param option
     * @param style
     * @return render result
     * @see RythmEngine#toString(Object, org.rythmengine.toString.ToStringOption, org.rythmengine.toString.ToStringStyle)
     */
    public static String toString(Object obj, ToStringOption option, ToStringStyle style) {
        return engine().toString(obj, option, style);
    }

    /**
     * @param obj
     * @param option
     * @param style
     * @return render result
     * @see RythmEngine#commonsToString(Object, org.rythmengine.toString.ToStringOption, org.apache.commons.lang3.builder.ToStringStyle)
     */
    public static String commonsToString(Object obj, ToStringOption option, org.apache.commons.lang3.builder.ToStringStyle style) {
        return engine().commonsToString(obj, option, style);
    }

    /**
     * Alias of {@link #renderString(String, Object...)}
     *
     * @param template
     * @param args
     * @return render result
     * @see RythmEngine#renderString(String, Object...)
     */
    public static String renderStr(String template, Object... args) {
        return engine().renderString(template, args);
    }

    /**
     * @param template
     * @param args
     * @return render result
     * @see RythmEngine#renderString(String, Object...)
     */
    public static String renderString(String template, Object... args) {
        return engine().renderString(template, args);
    }

    /**
     * @param template
     * @param args
     * @return render result
     * @see RythmEngine#renderIfTemplateExists(String, Object...)
     */
    public static String renderIfTemplateExists(String template, Object... args) {
        return engine().renderIfTemplateExists(template, args);
    }
}

19 View Complete Implementation : WordprocessingMLRythmTemplate.java
Copyright Apache License 2.0
Author : hiwepy
public void setEngine(RythmEngine engine) {
    this.engine = engine;
}

19 View Complete Implementation : ExtensionManager.java
Copyright Apache License 2.0
Author : rythmengine
public clreplaced ExtensionManager {

    private final Set<IJavaExtension> _extensions = new HashSet<IJavaExtension>();

    private final List<IFormatter> _fmts = new ArrayList<IFormatter>();

    private final RythmEngine engine;

    public ExtensionManager(RythmEngine engine) {
        if (null == engine)
            throw new NullPointerException();
        this.engine = engine;
    }

    /**
     * Add a Java extension
     *
     * @param javaExtension
     */
    public void registerJavaExtension(IJavaExtension javaExtension) {
        _extensions.add(javaExtension);
    }

    Iterable<IJavaExtension> javaExtensions() {
        return _extensions;
    }

    /**
     * Is a specified method name a java extension?
     *
     * @param s
     * @return true if the name is a java extension
     */
    public boolean isJavaExtension(String s) {
        for (IJavaExtension ext : _extensions) {
            if (S.isEqual(s, ext.methodName())) {
                return true;
            }
        }
        return false;
    }

    public ExtensionManager registerUserDefinedParsers(IParserFactory... parsers) {
        return registerUserDefinedParsers(null, parsers);
    }

    /**
     * Register a special case parser to a dialect
     * <p/>
     * <p>for example, the play-rythm plugin might want to register a special case parser to
     * process something like @{Controller.actionMethod()} or &{'MSG_ID'} etc to "replacedid"
     * and "play-groovy" dialects
     *
     * @param dialect
     * @param parsers
     */
    public ExtensionManager registerUserDefinedParsers(String dialect, IParserFactory... parsers) {
        engine.dialectManager().registerExternalParsers(dialect, parsers);
        return this;
    }

    private List<IExpressionProcessor> expressionProcessors = new ArrayList<IExpressionProcessor>();

    public ExtensionManager registerExpressionProcessor(IExpressionProcessor p) {
        if (!expressionProcessors.contains(p))
            expressionProcessors.add(p);
        return this;
    }

    public Iterable<IExpressionProcessor> expressionProcessors() {
        return expressionProcessors;
    }

    private List<ICodeType> codeTypeList = new ArrayList<ICodeType>();

    public ExtensionManager registerCodeType(ICodeType type) {
        codeTypeList.add(type);
        return this;
    }

    public Iterable<ICodeType> templateLangs() {
        return codeTypeList;
    }

    public boolean hasTemplateLangs() {
        return !codeTypeList.isEmpty();
    }

    public ExtensionManager registerFormatter(IFormatter fmt) {
        _fmts.add(fmt);
        return this;
    }

    public Iterable<IFormatter> formatters() {
        return new Iterable<IFormatter>() {

            @Override
            public Iterator<IFormatter> iterator() {
                return _fmts.iterator();
            }
        };
    }
}

19 View Complete Implementation : TemplateClass.java
Copyright Apache License 2.0
Author : rythmengine
public ITemplate asTemplate(ITemplate caller, RythmEngine engine) {
    TemplateBase tb = (TemplateBase) caller;
    TemplateBase tmpl = (TemplateBase) templateInstance_(engine).__cloneMe(engine, caller);
    tmpl.__prepareRender(tb.__curCodeType(), tb.__curLocale(), engine);
    return tmpl;
}

19 View Complete Implementation : RythmPlugin.java
Copyright Apache License 2.0
Author : rythmengine
private void registerJavaTags(RythmEngine engine) {
    long l = System.currentTimeMillis();
    // -- register application java tags
    List<ApplicationClreplacedes.ApplicationClreplaced> clreplacedes = Play.clreplacedes.getreplacedignableClreplacedes(FastRythmTag.clreplaced);
    for (ApplicationClreplacedes.ApplicationClreplaced ac : clreplacedes) {
        registerJavaTag(ac.javaClreplaced, engine);
    }
    // -- register PlayRythm build-in tags
    Clreplaced<?>[] ca = FastRythmTags.clreplaced.getDeclaredClreplacedes();
    for (Clreplaced<?> c : ca) {
        registerJavaTag(c, engine);
    }
    debug("%sms to register rythm java tags", System.currentTimeMillis() - l);
}

19 View Complete Implementation : TemplateClass.java
Copyright Apache License 2.0
Author : rythmengine
@SuppressWarnings("unchecked")
private Clreplaced<?> loadJavaClreplaced() throws Exception {
    if (null == javaSource) {
        if (null == javaSource) {
            refresh(false);
        }
    }
    RythmEngine engine = engine();
    TemplateClreplacedLoader cl = engine.clreplacedLoader();
    if (null == cl) {
        throw new NullPointerException();
    }
    Clreplaced<?> c = cl.loadClreplaced(name, true);
    if (null == javaClreplaced) {
        javaClreplaced = (Clreplaced<ITemplate>) c;
    }
    return c;
}

19 View Complete Implementation : DialectBase.java
Copyright Apache License 2.0
Author : rythmengine
@Override
public CodeBuilder createCodeBuilder(String template, String clreplacedName, String tagName, TemplateClreplaced templateClreplaced, RythmEngine engine) {
    return new CodeBuilder(template, clreplacedName, tagName, templateClreplaced, engine, this);
}

19 View Complete Implementation : SandboxModel.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Created by luog on 20/06/2014.
 */
public clreplaced SandboxModel {

    private String id = S.random();

    private RythmEngine engine;

    public SandboxModel(String id, RythmEngine engine) {
        this.id = id;
        this.engine = engine;
    }

    @Override
    public String toString() {
        return engine.subsreplacedute("Bar[@1]", id);
    }
}

19 View Complete Implementation : RythmView.java
Copyright Apache License 2.0
Author : actframework
private Template loadTemplateFromResource(String resourcePath, App app) {
    RythmEngine engine = getEngine(app);
    return RythmTemplate.find(engine, resourcePath);
}

19 View Complete Implementation : TemplateResourceBase.java
Copyright Apache License 2.0
Author : rythmengine
public static ICodeType getTypeOfPath(RythmEngine engine, String s) {
    String suffix = engine.conf().resourceNameSuffix();
    if (s.endsWith(suffix)) {
        int pos = s.lastIndexOf(suffix);
        if (pos > -1)
            s = s.substring(0, pos);
    }
    ICodeType codeType = engine.conf().defaultCodeType();
    if (s.endsWith(".html") || s.endsWith(".htm")) {
        codeType = ICodeType.DefImpl.HTML;
    } else if (s.endsWith(".js")) {
        codeType = ICodeType.DefImpl.JS;
    } else if (s.endsWith(".json")) {
        codeType = ICodeType.DefImpl.JSON;
    } else if (s.endsWith(".xml")) {
        codeType = ICodeType.DefImpl.XML;
    } else if (s.endsWith(".csv")) {
        codeType = ICodeType.DefImpl.CSV;
    } else if (s.endsWith(".css")) {
        codeType = ICodeType.DefImpl.CSS;
    }
    return codeType;
}

19 View Complete Implementation : TemplateClass.java
Copyright Apache License 2.0
Author : rythmengine
public ITemplate asTemplate(RythmEngine engine) {
    return asTemplate(null, null, engine);
}

19 View Complete Implementation : TagBase.java
Copyright Apache License 2.0
Author : rythmengine
protected void __triggerRenderEvent(IEvent<Void, ITemplate> event, RythmEngine engine) {
    // do not trigger render events while calling as a tag
    if (calling)
        return;
    event.trigger(engine, this);
}

19 View Complete Implementation : TemplateClass.java
Copyright Apache License 2.0
Author : rythmengine
public ITemplate asTemplate(ICodeType type, Locale locale, RythmEngine engine) {
    if (null == name || engine.isDevMode()) {
        refresh(false);
    }
    TemplateBase tmpl = (TemplateBase) templateInstance_(engine).__cloneMe(engine(), null);
    if (tmpl != null) {
        tmpl.__prepareRender(type, locale, engine);
    }
    return tmpl;
}

19 View Complete Implementation : RythmView.java
Copyright Apache License 2.0
Author : actframework
@Override
protected Template loadInlineTemplate(String content) {
    RythmEngine engine = getEngine(Act.app());
    return new RythmTemplate(engine, content, true);
}

19 View Complete Implementation : TagBase.java
Copyright Apache License 2.0
Author : rythmengine
@Override
public ITemplate __cloneMe(RythmEngine engine, ITemplate caller) {
    TagBase newTag = (TagBase) super.__cloneMe(engine, caller);
    // newTag.setBody(null);
    // newTag.__buffer = new StringBuilder();
    return newTag;
}

18 View Complete Implementation : Token.java
Copyright Apache License 2.0
Author : rythmengine
public clreplaced Token extends TextBuilder {

    private Token() {
    }

    public static final Token EMPTY_TOKEN = new Token();

    // for https://github.com/greenlaw110/Rythm/issues/146
    public static final Token EMPTY_TOKEN2 = new Token();

    public static clreplaced StringToken extends Token {

        public String constId = null;

        public StringToken(String s, IContext ctx) {
            super(s, ctx);
        }

        public StringToken(String s, IContext context, boolean disableCompactMode) {
            super(s, context, disableCompactMode);
        }

        public StringToken mergeWith(BlockToken.LiteralBlock block) {
            StringToken merged = new StringToken(s, ctx, disableCompactMode);
            merged.line = block.line;
            merged.s += "{";
            return merged;
        }

        public StringToken mergeWith(StringToken st) {
            StringToken merged = new StringToken(s, ctx, disableCompactMode);
            merged.line = st.line;
            String s = st.s;
            s = st.compact(s);
            merged.s += s;
            return merged;
        }

        @Override
        public boolean removeLeadingLineBreak() {
            // String s0 = s;
            s = s.replaceFirst("^[ \\t\\x0B\\f]*\\n", "");
            return true;
        }

        public int getLineNo() {
            return line;
        }

        public String s() {
            return s;
        }

        @Override
        public String toString() {
            return s;
        }

        @Override
        protected void output() {
            RythmEngine.OutputMode mode = RythmEngine.outputMode();
            if (mode.writeOutput()) {
                if (null == constId)
                    return;
                p("p(").p(constId).p(");");
                pline();
            } else {
                super.output();
            }
        }

        @Override
        public int hashCode() {
            return s.hashCode() + (compactMode() ? 1 : -1);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == this)
                return true;
            if (obj instanceof StringToken) {
                StringToken st = (StringToken) obj;
                return st.compactMode() == compactMode() && st.s.equals(s);
            }
            return false;
        }

        public boolean empty() {
            return S.empty(s);
        }
    }

    protected static final ILogger logger = Logger.get(Token.clreplaced);

    protected String s;

    protected IContext ctx;

    protected int line;

    protected boolean disableCompactMode = false;

    public boolean removeNextLineBreak = false;

    public boolean removeLeadingLineBreak() {
        return false;
    }

    protected boolean compactMode() {
        if (disableCompactMode)
            return false;
        return (null == ctx ? true : ctx.compactMode());
    }

    private RythmEngine engine = null;

    private Iterable<IJavaExtension> javaExtensions = null;

    private boolean transformEnabled = true;

    /*
     * Indicate whether token parse is good
     */
    private boolean ok = true;

    protected final void fail() {
        ok = false;
    }

    protected Token(String s, TextBuilder caller) {
        this(s, caller, false);
    }

    protected Token(String s, TextBuilder caller, boolean disableCompactMode) {
        super(caller);
        this.s = checkDynaExp(s);
        line = -1;
        this.disableCompactMode = disableCompactMode;
        // TODO: dangerous engine replacedignment here. only called by AppendXXToken in AutoToStringCodeBuilder
        this.engine = Rythm.engine();
        this.javaExtensions = engine.extensionManager().javaExtensions();
        RythmConfiguration conf = engine.conf();
        this.transformEnabled = conf.transformEnabled();
    }

    public Token(String s, IContext context) {
        this(s, context, false);
    }

    public Token(String s, IContext context, boolean disableCompactMode) {
        super(null == context ? null : context.getCodeBuilder());
        this.s = s;
        ctx = context;
        line = (null == context) ? -1 : context.currentLine();
        this.engine = null == ctx ? Rythm.engine() : ctx.getEngine();
        this.javaExtensions = engine.extensionManager().javaExtensions();
        this.disableCompactMode = disableCompactMode;
        RythmConfiguration conf = engine.conf();
        this.transformEnabled = conf.transformEnabled();
    }

    public boolean test(String line) {
        return true;
    }

    public boolean isOk() {
        return ok;
    }

    public final Token build() {
        if (ok)
            output();
        else {
            pp(s);
        }
        return this;
    }

    public final Token build(IContext includeCtx) {
        IContext ctx0 = ctx;
        ctx = includeCtx;
        try {
            build();
        } finally {
            ctx = ctx0;
        }
        return this;
    }

    protected void output() {
        if (null == s || "".equals(s))
            return;
        pp(s);
    }

    private static final Regex R_ = new Regex("^\\s*(?@())\\s*$");

    /**
     * strip the outer brackets of the given string s
     *
     * @param s
     * @return - the stripped string
     */
    private static String stripOuterBrackets(String s) {
        try {
            if (S.isEmpty(s))
                return s;
            if (R_.search(s)) {
                // strip out the outer brackets
                s = R_.stringMatched();
                s = s.substring(1);
                s = s.substring(0, s.length() - 1);
            }
        } catch (RuntimeException re) {
            // this unfortunately happens - so at least make it debuggable
            throw re;
        }
        return s;
    }

    private static final Pattern P_ELVIS = Pattern.compile("(.*)(\\s*\\?\\s*:\\s*.*)");

    private static String[] stripElvis(String s) {
        if (S.isEmpty(s))
            return new String[] { "", "" };
        s = stripOuterBrackets(s);
        Matcher m = P_ELVIS.matcher(s);
        if (m.matches()) {
            String s0 = m.group(1);
            String s1 = m.group(2);
            return new String[] { s0, s1 };
        } else {
            return new String[] { s, "" };
        }
    }

    private static String processElvis(String s) {
        if (S.isEmpty(s))
            return s;
        String[] sa = stripElvis(s);
        s = sa[0];
        String elvis = sa[1];
        if (S.isEmpty(elvis))
            return s;
        elvis = elvis.replaceFirst("^\\s*\\?\\s*:\\s*", "");
        return String.format("((__isDefVal(%1$s)) ? %2$s : %1$s)", s, elvis);
    }

    protected final void outputExpression(List<String> nullValueTester) {
        int size = nullValueTester.size();
        for (String s : nullValueTester) {
            p("if (null != ").p(s).p(") {\n\t");
        }
        outputExpression();
        pn();
        for (int i = 0; i < size; ++i) {
            pn("}");
        }
    }

    protected final void outputExpression() {
        outputExpression(true);
    }

    protected final void outputExpression(boolean needsPrint) {
        if (S.isEmpty(s))
            return;
        String s = processExtensions(false);
        if (needsPrint)
            p("\ntry{pe(").p(s).p(");} catch (RuntimeException e) {__handleTemplateExecutionException(e);} ");
        else
            p("\ntry{").p(s).p(";} catch (RuntimeException e) {__handleTemplateExecutionException(e);} ");
        pline();
    }

    private boolean dynaExp = false;

    private String evalStr(String s) {
        if (!dynaExp)
            return s;
        return "__eval(\"" + S.escapeJava(s) + "\")";
    }

    private String checkDynaExp(String s) {
        if (S.empty(s))
            return s;
        boolean b = (s.endsWith("@"));
        if (b) {
            dynaExp = true;
            return s.substring(0, s.length() - 1);
        } else {
            return s;
        }
    }

    private String processExtensions(boolean stripExtensions) {
        if (!transformEnabled)
            return evalStr(s);
        RythmEngine engine = this.engine;
        String s0 = s;
        boolean outerBracketsStripped;
        s = stripOuterBrackets(s);
        s = checkDynaExp(s);
        outerBracketsStripped = s != s0;
        clreplaced Pair {

            IJavaExtension extension;

            String signature;

            Pair(IJavaExtension e, String s) {
                extension = e;
                signature = s;
            }
        }
        Stack<Pair> allMatched = new Stack<Pair>();
        // try parse java extension first
        while (true) {
            boolean matched = false;
            for (IJavaExtension e : javaExtensions) {
                Pattern p = e.pattern1();
                Matcher m = p.matcher(s);
                if (m.matches()) {
                    matched = true;
                    String signature = null;
                    if (!(e instanceof IJavaExtension.VoidParameterExtension)) {
                        signature = m.group(1);
                        if (null == signature) {
                            signature = m.group(2);
                        }
                    }
                    m = e.pattern2().matcher(s);
                    s = m.replaceAll("");
                    allMatched.push(new Pair(e, signature));
                }
            }
            if (!matched)
                break;
        }
        boolean hasJavaExtension = !allMatched.empty();
        if (hasJavaExtension) {
            // process inner elvis expression
            s = processElvis(s);
            s = evalStr(s);
            while (!allMatched.empty()) {
                Pair p = allMatched.pop();
                if (!stripExtensions) {
                    s = p.extension.extend(s, p.signature);
                }
            }
        } else {
            // then check elvsi and then java extensions again
            String[] sa = stripElvis(s);
            s = sa[0];
            String elvis = sa[1];
            while (true) {
                boolean matched = false;
                for (IJavaExtension e : javaExtensions) {
                    Pattern p = e.pattern1();
                    Matcher m = p.matcher(s);
                    if (m.matches()) {
                        matched = true;
                        String signature = (e instanceof IJavaExtension.VoidParameterExtension) ? null : m.group(1);
                        m = e.pattern2().matcher(s);
                        s = m.replaceAll("");
                        allMatched.push(new Pair(e, signature));
                    }
                }
                if (!matched)
                    break;
            }
            s = evalStr(s);
            while (!stripExtensions && !allMatched.empty()) {
                // process inner elvis expression
                s = processElvis(s);
                Pair p = allMatched.pop();
                s = p.extension.extend(s, p.signature);
            }
            if (!S.isEmpty(elvis)) {
                // process outer elvis expression
                elvis = elvis.replaceFirst("^\\s*\\?\\s*:\\s*", "");
                s = String.format("((__isDefVal(%1$s)) ? %2$s : %1$s)", s, elvis);
            }
        }
        if (outerBracketsStripped) {
            s = String.format("(%s)", s);
        }
        s = compact(s);
        for (IExpressionProcessor p : engine.extensionManager().expressionProcessors()) {
            String result = p.process(s, this);
            if (null != result) {
                // remove line breaks so that we can easily handle line numbers
                return S.removeAllLineBreaks(result);
            }
        }
        return s;
    }

    public Token ptline(String msg, Object... args) {
        String s = String.format(msg, args);
        p("\t").p(s);
        pline();
        return this;
    }

    public Token p2tline(String msg, Object... args) {
        String s = String.format(msg, args);
        p("\t\t").p(s);
        pline();
        return this;
    }

    public Token p3tline(String msg, Object... args) {
        String s = String.format(msg, args);
        p("\t\t\t").p(s);
        pline();
        return this;
    }

    public Token p4tline(String msg, Object... args) {
        String s = String.format(msg, args);
        p("\t\t\t\t").p(s);
        pline();
        return this;
    }

    public Token p5tline(String msg, Object... args) {
        String s = String.format(msg, args);
        p("\t\t\t\t\t").p(s);
        pline();
        return this;
    }

    public Token pline(String msg, Object... args) {
        String s = String.format(msg, args);
        p(s);
        pline();
        return this;
    }

    public Token pline() {
        p(" //line: ").pn(line);
        return this;
    }

    protected void pp(String s) {
        s = compact(s);
        if (compactMode()) {
            s = s.replaceAll("(\\r?\\n)+", "\\\\n").replaceAll("\"", "\\\\\"");
        } else {
            s = s.replaceAll("(\\r?\\n)", "\\\\n").replaceAll("\"", "\\\\\"");
        }
        p("p(\"").p(s).p("\");");
        pline();
    }

    public Token clone(TextBuilder caller) {
        return (Token) super.clone(caller);
    }

    private static final Pattern P_C1 = Pattern.compile("\\n+", Pattern.DOTALL);

    private static final Pattern P_C2 = Pattern.compile("[ \\t\\x0B\\f]+", Pattern.DOTALL);

    private static final Pattern P_C3 = Pattern.compile("[ \\t\\x0B\\f]+\\n", Pattern.DOTALL);

    private static final Pattern P_C4 = Pattern.compile("\\n[ \\t\\x0B\\f]+", Pattern.DOTALL);

    private static String compact_(String s) {
        if (s.matches("(\\n\\r|\\r\\n|[\\r\\n])+")) {
            return "\n";
        }
        Matcher m = P_C1.matcher(s);
        s = m.replaceAll("\n");
        m = P_C2.matcher(s);
        s = m.replaceAll(" ");
        m = P_C3.matcher(s);
        s = m.replaceAll("\n");
        m = P_C4.matcher(s);
        s = m.replaceAll("\n");
        return s;
    // String[] lines = s.split("[\\r\\n]+");
    // if (0 == lines.length) return "";
    // TextBuilder tb = new TextBuilder();
    // int i = 0;
    // boolean startsWithSpace = s.startsWith(" ") || s.startsWith("\t");
    // boolean endsWithSpace = s.endsWith(" ") || s.endsWith("\t");
    // if (startsWithSpace) tb.p(" ");
    // for (String line : lines) {
    // if (i++ > 0) tb.p("\n");
    // line = line.replaceAll("[ \t]+", " ").trim();
    // tb.p(line);
    // }
    // if (endsWithSpace) tb.p(" ");
    // return tb.toString();
    }

    private static String processLineBreaks_(String s) {
        return s;
    }

    public void compact() {
        s = compact(s);
    }

    protected String compact(String s) {
        return compactMode() ? compact_(s) : processLineBreaks_(s);
    }

    public static String processRythmExpression(String s, IContext ctx) {
        Token token = new Token(s, ctx);
        return token.processExtensions(false);
    }

    public static String stripJavaExtension(String s, IContext ctx) {
        Token token = new Token(s, ctx);
        return token.processExtensions(true);
    }
}

18 View Complete Implementation : ResourceLoaderBase.java
Copyright Apache License 2.0
Author : rythmengine
@Override
public TemplateClreplaced tryLoadTemplate(String tmplName, RythmEngine engine, TemplateClreplaced callerClreplaced, ICodeType codeType) {
    return tryLoadTemplate(tmplName, engine, callerClreplaced, codeType, true);
}

18 View Complete Implementation : ResourceLoaderBase.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Implement common logic of an {@link ITemplateResourceLoader}
 */
public abstract clreplaced ResourceLoaderBase implements ITemplateResourceLoader {

    protected static ILogger logger = Logger.get(ResourceLoaderBase.clreplaced);

    private RythmEngine engine;

    public RythmEngine getEngine() {
        return this.engine;
    }

    public void setEngine(RythmEngine engine) {
        this.engine = engine;
    }

    public String getFullName(TemplateClreplaced tc) {
        String key = tc.getKey().toString();
        if (key.startsWith("/") || key.startsWith("\\"))
            key = key.substring(1);
        String root = getResourceLoaderRoot();
        if (key.startsWith(root)) {
            key = key.replace(root, "");
        }
        if (key.startsWith("/") || key.startsWith("\\"))
            key = key.substring(1);
        int pos = key.lastIndexOf(".");
        if (-1 != pos)
            key = key.substring(0, pos);
        key = key.replace('/', '.').replace('\\', '.');
        key += tc.codeType.resourceNameSuffix();
        return key;
    }

    protected RythmEngine getDefaultEngine() {
        return Rythm.engine();
    }

    @Override
    public TemplateClreplaced tryLoadTemplate(String tmplName, RythmEngine engine, TemplateClreplaced callerClreplaced, ICodeType codeType) {
        return tryLoadTemplate(tmplName, engine, callerClreplaced, codeType, true);
    }

    /**
     * try loading the given template
     * @param tmplName
     * @param engine
     * @param callerClreplaced
     * @param codeType
     * @param processTagName
     * @return the template Clreplaced
     */
    private TemplateClreplaced tryLoadTemplate(String tmplName, RythmEngine engine, TemplateClreplaced callerClreplaced, ICodeType codeType, boolean processTagName) {
        // logger.info(">>> try load %s on [%s] with processTagName: %s", tmplName, callerClreplaced.getKey(), processTagName);
        if (null == engine) {
            engine = getDefaultEngine();
        }
        if (engine.templateRegistered(tmplName)) {
            return null;
        }
        String rythmSuffix = engine.conf().resourceNameSuffix();
        final List<String> suffixes = new ArrayList<String>(Arrays.asList(RythmEngine.VALID_SUFFIXES));
        if (null == codeType) {
            codeType = TemplateResourceBase.getTypeOfPath(engine, tmplName);
        }
        if (ICodeType.DefImpl.RAW == codeType) {
            // use caller's code type
            codeType = callerClreplaced.codeType;
        }
        final String tagNameOrigin = tmplName;
        boolean hreplaceduffix = false;
        String suffix = "";
        if (processTagName) {
            boolean withRythmSuffix = S.notEmpty(rythmSuffix);
            for (String s : suffixes) {
                if (tmplName.endsWith(s)) {
                    tmplName = tmplName.substring(0, tmplName.lastIndexOf(s));
                    suffix = s;
                    hreplaceduffix = true;
                    break;
                }
                if (withRythmSuffix && (tmplName.endsWith(s) || tmplName.endsWith(s + rythmSuffix))) {
                    tmplName = tmplName.substring(0, tmplName.lastIndexOf(s));
                    suffix = s + rythmSuffix;
                    hreplaceduffix = true;
                    break;
                }
            }
        }
        tmplName = tmplName.replace('.', '/');
        String sfx = codeType.resourceNameSuffix();
        if (S.notEmpty(sfx) && !suffixes.get(0).equals(sfx)) {
            suffixes.remove(sfx);
            suffixes.add(0, sfx);
        }
        final List<String> roots = new ArrayList<String>();
        String root0 = this.getResourceLoaderRoot().replace('\\', '/');
        if (root0.endsWith("/")) {
            root0 = root0.substring(0, root0.length() - 1);
        }
        roots.add(root0);
        // call template using relative path
        String currentPath = callerClreplaced.getKey().toString();
        int pos = currentPath.lastIndexOf("/");
        if (-1 != pos) {
            currentPath = currentPath.substring(0, pos);
            if (currentPath.startsWith(root0)) {
                if (currentPath.length() > root0.length()) {
                    roots.add(0, currentPath);
                }
            } else {
                if (currentPath.startsWith("/")) {
                    currentPath = currentPath.substring(1);
                }
                if (!currentPath.startsWith(root0))
                    currentPath = root0 + "/" + currentPath;
                roots.add(0, currentPath);
            }
        }
        // call tag with import path
        if (null != callerClreplaced.importPaths) {
            for (String s : callerClreplaced.importPaths) {
                if (s.startsWith("java")) {
                    continue;
                }
                roots.add(0, root0 + "/" + s.replace('.', '/'));
            }
        }
        String tmplName0 = tmplName;
        for (String root : roots) {
            String tmplName1 = tmplName0;
            if (root.startsWith("/") && !tmplName1.startsWith("/")) {
                tmplName1 = "/" + tmplName0;
            }
            tmplName = tmplName1.startsWith(root) ? tmplName1 : root + "/" + tmplName0;
            if (hreplaceduffix) {
                ITemplateResource resource = load(tmplName + suffix);
                if (null == resource || !resource.isValid()) {
                    continue;
                }
                TemplateClreplaced tc = engine.resourceManager().resourceLoaded(resource, false);
                return tc;
            } else {
                for (String suffix0 : suffixes) {
                    String path = tmplName + suffix0;
                    ITemplateResource resource = load(path);
                    if (null == resource || !resource.isValid()) {
                        continue;
                    }
                    TemplateClreplaced tc = engine.resourceManager().resourceLoaded(resource, false);
                    return tc;
                }
            }
        }
        TemplateClreplaced tc = processTagName ? tryLoadTemplate(tagNameOrigin, engine, callerClreplaced, codeType, false) : null;
        if (null == tc) {
            TemplateResourceManager.reportNonResource(tmplName);
        }
        return tc;
    }

    @Override
    public void scan(TemplateResourceManager manager) {
        logger.warn("Resource scan not supported by %s", getClreplaced().getName());
    }
}

18 View Complete Implementation : TemplateResourceManager.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * The template resource manager manages all template resource loaders and also cache the resource after they
 * get loaded
 */
public clreplaced TemplateResourceManager {

    @SuppressWarnings("unused")
    private static final ILogger logger = Logger.get(TemplateResourceManager.clreplaced);

    /**
     * NULL TemplateResource
     */
    @SuppressWarnings("serial")
    public static final ITemplateResource NULL = new ITemplateResource() {

        // this NULL TemplateResource can actually carry an error
        // might not be necessary but is there in any case
        private Throwable error;

        @Override
        public Object getKey() {
            return null;
        }

        @Override
        public String getSuggestedClreplacedName() {
            return null;
        }

        @Override
        public String asTemplateContent() {
            return null;
        }

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

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

        @Override
        public ICodeType codeType(RythmEngine engine) {
            return null;
        }

        @Override
        public ITemplateResourceLoader getLoader() {
            return null;
        }

        @Override
        public Throwable getError() {
            return error;
        }

        @Override
        public void setError(Throwable error) {
            this.error = error;
        }
    };

    private RythmEngine engine;

    private Map<Object, ITemplateResource> cache = new HashMap<Object, ITemplateResource>();

    private List<ITemplateResourceLoader> loaders;

    private FileResourceLoader adhocFileLoader = null;

    // the <key, loader> map allows
    private Map<Object, ITemplateResourceLoader> whichLoader = new HashMap<Object, ITemplateResourceLoader>();

    private boolean typeInference;

    /**
     * Store the String that is NOT a resource
     */
    private static Set<String> blackList = new HashSet<String>();

    private static ThreadLocal<Stack<Set<String>>> tmpBlackList = new ThreadLocal<Stack<Set<String>>>() {

        @Override
        protected Stack<Set<String>> initialValue() {
            return new Stack<Set<String>>();
        }
    };

    public static void setUpTmpBlackList() {
        tmpBlackList.get().push(new HashSet<String>());
    }

    public static void reportNonResource(String str) {
        Stack<Set<String>> ss = tmpBlackList.get();
        if (ss.isEmpty()) {
            // invoked dynamically when running @invoke(...)
            tmpBlackList.remove();
            blackList.add(str);
        } else {
            ss.peek().add(str);
        }
    }

    public static void commitTmpBlackList() {
        Stack<Set<String>> sss = tmpBlackList.get();
        if (!sss.isEmpty()) {
            Set<String> ss = sss.pop();
            blackList.addAll(ss);
        }
        if (sss.isEmpty()) {
            tmpBlackList.remove();
        }
    }

    public static void rollbackTmpBlackList() {
        Stack<Set<String>> sss = tmpBlackList.get();
        if (!sss.isEmpty()) {
            sss.pop();
        }
        if (sss.isEmpty()) {
            tmpBlackList.remove();
        }
    }

    public static void cleanUpTmplBlackList() {
        // Stack<Set<String>> ss = tmpBlackList.get();
        // if (null != ss) {
        // ss.clear();
        // }
        tmpBlackList.remove();
    }

    /**
     * construct the TemplateResourceManager for the give engine
     * @param engine
     */
    public TemplateResourceManager(RythmEngine engine) {
        this.engine = engine;
        RythmConfiguration conf = engine.conf();
        typeInference = conf.typeInferenceEnabled();
        loaders = new ArrayList(conf.getList(RythmConfigurationKey.RESOURCE_LOADER_IMPLS, ITemplateResourceLoader.clreplaced));
        if (!loaders.isEmpty()) {
            for (ITemplateResourceLoader loader : loaders) {
                loader.setEngine(this.engine);
            }
            Boolean defLoader = conf.get(RythmConfigurationKey.RESOURCE_DEF_LOADER_ENABLED);
            if (!defLoader) {
                return;
            }
        }
        List<URI> roots = conf.templateHome();
        for (URI root : roots) {
            if (null == root)
                continue;
            String scheme = root.getScheme();
            if (S.eq(scheme, "jar")) {
                String s = root.getSchemeSpecificPart();
                int pos = s.indexOf(".jar!");
                String home = s.substring(pos + 5);
                ClreplacedpathResourceLoader crl = new ClreplacedpathResourceLoader(engine, home);
                loaders.add(crl);
            } else if (S.eq(scheme, "file")) {
                FileResourceLoader frl = new FileResourceLoader(engine, new File(root.getPath()));
                if (null == adhocFileLoader) {
                    adhocFileLoader = frl;
                }
                loaders.add(frl);
            }
        }
    }

    public void addResourceLoader(ITemplateResourceLoader loader) {
        if (!loaders.contains(loader))
            loaders.add(loader);
    }

    public void prependResourceLoader(ITemplateResourceLoader loader) {
        if (!loaders.contains(loader))
            loaders.add(0, loader);
    }

    private ITemplateResource cache(ITemplateResource resource) {
        return cache(null, resource);
    }

    private ITemplateResource cache(Object key, ITemplateResource resource) {
        if (resource.isValid()) {
            cache.put(resource.getKey(), resource);
            if (null != key) {
                cache.put(key, resource);
            }
        }
        return resource;
    }

    public TemplateClreplaced tryLoadTemplate(String tmplName, TemplateClreplaced callerClreplaced, ICodeType codeType) {
        if (blackList.contains(tmplName)) {
            // logger.info(">>> %s is in the black list", tmplName);
            return null;
        }
        TemplateClreplaced tc = null;
        RythmEngine engine = this.engine;
        if (null != callerClreplaced) {
            ITemplateResourceLoader loader = whichLoader(callerClreplaced.templateResource);
            if (null != loader) {
                return loader.tryLoadTemplate(tmplName, engine, callerClreplaced, codeType);
            }
        }
        for (ITemplateResourceLoader loader : loaders) {
            tc = loader.tryLoadTemplate(tmplName, engine, callerClreplaced, codeType);
            if (null != tc) {
                break;
            }
        }
        return tc;
    }

    public ITemplateResource get(File file) {
        return cache(new FileTemplateResource(file, adhocFileLoader));
    }

    public ITemplateResource get(String str) {
        ITemplateResource resource = getResource(str);
        if (!resource.isValid()) {
            resource = new StringTemplateResource(str);
        }
        return cache(resource);
    }

    public ITemplateResourceLoader whichLoader(ITemplateResource resource) {
        return whichLoader.get(resource.getKey());
    }

    public ITemplateResource getResource(String key) {
        ITemplateResource resource = cache.get(key);
        if (null != resource)
            return resource;
        if (Sandbox.isRestricted())
            return NULL;
        for (ITemplateResourceLoader loader : loaders) {
            resource = loader.load(key);
            if (null != resource && resource.isValid()) {
                whichLoader.put(resource.getKey(), loader);
                whichLoader.put(key, loader);
                if (key != resource.getKey() && resource instanceof ClreplacedpathTemplateResource) {
                    ((ClreplacedpathTemplateResource) resource).setKey2(key);
                }
                break;
            }
        }
        return null == resource ? NULL : cache(key, resource);
    }

    public void scan() {
        for (ITemplateResourceLoader loader : loaders) {
            loader.scan(this);
        }
    }

    public void resourceLoaded(final ITemplateResource resource) {
        resourceLoaded(resource, true);
    }

    public TemplateClreplaced resourceLoaded(final ITemplateResource resource, boolean async) {
        final ITemplateResourceLoader loader = resource.getLoader();
        // if (!async) { no async load at the moment
        if (true) {
            whichLoader.put(resource.getKey(), loader);
            return _resourceLoaded(resource);
        } else {
            loadingService.submit(new Callable<Object>() {

                @Override
                public Object call() throws Exception {
                    whichLoader.put(resource.getKey(), loader);
                    _resourceLoaded(resource);
                    return null;
                }
            });
            return null;
        }
    }

    private TemplateClreplaced _resourceLoaded(ITemplateResource resource) {
        if (!resource.isValid())
            return null;
        String key = S.str(resource.getKey());
        if (typeInference) {
            key += ParamTypeInferencer.uuid();
        }
        RythmEngine engine = this.engine;
        TemplateClreplaced tc = engine.clreplacedes().getByTemplate(key);
        if (null == tc) {
            tc = new TemplateClreplaced(resource, engine);
        }
        tc.asTemplate(engine);
        return tc;
    }

    private static clreplaced ScannerThreadFactory extends RythmThreadFactory {

        private ScannerThreadFactory() {
            super("rythm-scanner");
        }
    }

    /* 
     * At the moment we don't support parsing templates in parallel, so ...
     */
    private ScheduledExecutorService loadingService = new ScheduledThreadPoolExecutor(1, new ScannerThreadFactory());

    public void shutdown() {
        loadingService.shutdown();
    }
}

18 View Complete Implementation : SandboxExecutingService.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * A secure executing service run template in a separate thread in case there are infinite loop, and also set
 * the SecurityManager in the executing thread
 */
public clreplaced SandboxExecutingService {

    private static ILogger logger = Logger.get(SandboxExecutingService.clreplaced);

    private ScheduledExecutorService scheduler = null;

    private long timeout = 1000;

    private RythmEngine engine;

    private String code = null;

    public SandboxExecutingService(int poolSize, SandboxThreadFactory fact, long timeout, RythmEngine re, String code) {
        scheduler = new ScheduledThreadPoolExecutor(poolSize, fact, new ThreadPoolExecutor.AbortPolicy());
        this.timeout = timeout;
        engine = re;
        this.code = code;
    }

    private Future<Object> exec(final Map<String, Object> userCtx, final ITemplate tmpl, final String template, final File file, final Object... args) {
        return scheduler.submit(new Callable<Object>() {

            @Override
            public Object call() throws Exception {
                try {
                    engine.prepare(userCtx);
                    ITemplate t = tmpl;
                    if (null != t) {
                    } else if (null != template) {
                        t = engine.getTemplate(template, args);
                    } else if (null != file) {
                        t = engine.getTemplate(file, args);
                    } else {
                        throw new NullPointerException();
                    }
                    return t.__setSecureCode(code).render();
                } catch (Exception e) {
                    return e;
                }
            }
        });
    }

    public String execute(Map<String, Object> context, File template, Object... args) {
        if (null == template)
            throw new NullPointerException();
        Future<Object> f = null;
        try {
            f = exec(context, null, null, template, args);
            Object o = f.get(timeout, TimeUnit.MILLISECONDS);
            if (o instanceof RuntimeException)
                throw (RuntimeException) o;
            if (o instanceof Exception)
                throw new RuntimeException((Exception) o);
            return (null == o) ? "" : o.toString();
        } catch (RuntimeException e) {
            if (null != f) {
                f.cancel(true);
            }
            throw e;
        } catch (Exception e) {
            f.cancel(true);
            throw new RuntimeException(e);
        }
    }

    public String execute(Map<String, Object> context, String template, Object... args) {
        if (null == template)
            throw new NullPointerException();
        Future<Object> f = null;
        try {
            f = exec(context, null, template, null, args);
            Object o = f.get(timeout, TimeUnit.MILLISECONDS);
            if (o instanceof RuntimeException)
                throw (RuntimeException) o;
            if (o instanceof Exception)
                throw new RuntimeException((Exception) o);
            return (null == o) ? "" : o.toString();
        } catch (RuntimeException e) {
            if (null != f) {
                f.cancel(true);
            }
            throw e;
        } catch (TimeoutException e) {
            f.cancel(true);
            throw new SecurityException(e);
        } catch (Exception e) {
            f.cancel(true);
            throw new RuntimeException(e);
        }
    }

    public Future<Object> executeAsync(final ITemplate t) {
        final Future<Object> f = exec(null, t, null, null, null);
        // make sure it get cancelled if timeout
        scheduler.schedule(new Runnable() {

            @Override
            public void run() {
                f.cancel(true);
            }
        }, timeout, TimeUnit.MILLISECONDS);
        return f;
    }

    public void shutdown() {
        scheduler.shutdownNow();
    }

    @Override
    protected void finalize() throws Throwable {
        shutdown();
    }
}

18 View Complete Implementation : Tags.java
Copyright Apache License 2.0
Author : actframework
public void register(RythmEngine engine) {
    if (null == fastTags) {
        // something wrong before Dependency Injector initialized
        // register basic tags required by Error page template
        engine.registerFastTag(new ActMessage());
        return;
    }
    for (JavaTagBase tag : fastTags) {
        engine.registerFastTag(tag);
    }
}

18 View Complete Implementation : Bar.java
Copyright Apache License 2.0
Author : rythmengine
public static void main(String... args) throws Exception {
    Map<String, Object> config = new HashMap<String, Object>();
    config.put("engine.mode", "dev");
    config.put("home.template.dir", "p:/jfinal-rythm-demo/WebRoot/css");
    final RythmEngine engine = new RythmEngine(config);
    WL("Prod Mode:" + engine.isProdMode());
    WL(engine.render("my.html", "brian N"));
// engine.shutdown();
}

18 View Complete Implementation : Gh174Helper.java
Copyright Apache License 2.0
Author : rythmengine
public static void main(String[] args) throws Exception {
    final RythmEngine engine = prepareEngine();
    System.out.println(engine.mode());
    prepareTmplA();
    System.out.println(engine.render(TMPL_NAME, "world"));
    // unit system's round File.lastModified to 1 seconds
    Thread.sleep(1001);
    prepareTmplB();
    System.out.println(engine.render(TMPL_NAME, "world"));
}

18 View Complete Implementation : RythmTemplate.java
Copyright Apache License 2.0
Author : rythmengine
@Override
public void compile() {
    RythmEngine engine = this.engine();
    if (RythmPlugin.precompiling()) {
        try {
            refresh();
            tc.asTemplate(engine);
        } catch (Throwable e) {
            RythmPlugin.error(e, "Error precompiling template");
        }
    } else {
        refresh();
        if (isValid()) {
            ITemplate t = tc.asTemplate(engine);
        // TemplateResourceManager mgr = engine.resourceManager();
        // engine.registerTemplate(mgr.getFullTagName(tc), t);
        }
    }
// if (tc.isValid) tc.compile();
}

18 View Complete Implementation : RythmConfiguration.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Return <tt>RythmConfiguration</tt> instance of current RythmEngine, or
 * if it is not inside a RythmEngine runtime context, an {@link #EMPTY_CONF empty configuration}
 * is returned
 *
 * @return the configuration instance replacedociated with engine running in the current thread
 */
public static RythmConfiguration get() {
    RythmEngine engine = RythmEngine.get();
    return null != engine ? engine.conf() : EMPTY_CONF;
}

18 View Complete Implementation : RythmConfiguration.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Store the configuration for a {@link org.rythmengine.RythmEngine rythm engine}
 * instance. Different engine instance has different configuration instance.
 */
public clreplaced RythmConfiguration {

    private Map<String, Object> raw;

    private Map<RythmConfigurationKey, Object> data;

    private RythmEngine engine;

    /**
     * Construct a <code>RythmConfiguration</code> with a map. The map is copied to
     * the original map of the configuration instance
     *
     * @param configuration
     */
    public RythmConfiguration(Map<String, ?> configuration, RythmEngine engine) {
        raw = new HashMap<String, Object>(configuration);
        data = new HashMap<RythmConfigurationKey, Object>(configuration.size());
        this.engine = engine;
    }

    /**
     * Return configuration by {@link RythmConfigurationKey configuration key}
     *
     * @param key
     * @param <T>
     * @return the configured item
     */
    public <T> T get(RythmConfigurationKey key) {
        Object o = data.get(key);
        if (null == o) {
            o = key.getConfiguration(raw);
            if (null != o) {
                data.put(key, o);
            } else {
                data.put(key, RawData.NULL);
            }
        }
        if (o == RawData.NULL) {
            return null;
        } else {
            return (T) o;
        }
    }

    /**
     * Return a configuration value as list
     *
     * @param key
     * @param c
     * @param <T>
     * @return the list
     */
    public <T> List<T> getList(RythmConfigurationKey key, Clreplaced<T> c) {
        Object o = data.get(key);
        if (null == o) {
            List<T> l = RythmConfigurationKey.getImplList(key.getKey(), raw, c);
            data.put(key, l);
            return l;
        } else {
            return (List) o;
        }
    }

    /**
     * Look up configuration by a <code>String<code/> key. If the String key
     * can be converted into {@link RythmConfigurationKey rythm configuration key}, then
     * it is converted and call to {@link #get(RythmConfigurationKey)} method. Otherwise
     * the original configuration map is used to fetch the value from the string key
     *
     * @param key
     * @param <T>
     * @return the configured item
     */
    public <T> T get(String key) {
        if (key.startsWith("rythm.")) {
            key = key.replaceFirst("rythm.", "");
        }
        RythmConfigurationKey rk = RythmConfigurationKey.valueOfIgnoreCase(key);
        if (null != rk) {
            return get(rk);
        } else {
            return (T) raw.get(key);
        }
    }

    // speed up access to frequently accessed and non-modifiable configuration items
    private String _pluginVersion = null;

    /**
     * Return {@link RythmConfigurationKey#ENGINE_PLUGIN_VERSION plugin version} without lookup
     *
     * @return plugin version
     */
    public String pluginVersion() {
        if (null == _pluginVersion) {
            _pluginVersion = get(ENGINE_PLUGIN_VERSION);
        }
        return _pluginVersion;
    }

    private IByteCodeHelper _byteCodeHelper = null;

    /**
     * Return {@link RythmConfigurationKey#ENGINE_CLreplaced_LOADER_BYTE_CODE_HELPER_IMPL} without lookup
     *
     * @return the byte code helper
     */
    public IByteCodeHelper byteCodeHelper() {
        if (null == _byteCodeHelper) {
            _byteCodeHelper = get(ENGINE_CLreplaced_LOADER_BYTE_CODE_HELPER_IMPL);
        }
        return _byteCodeHelper;
    }

    private Boolean _play = null;

    /**
     * Return {@link RythmConfigurationKey#ENGINE_PLAYFRAMEWORK} without lookup
     *
     * @return true if the engine is used by playframework
     */
    public boolean playFramework() {
        if (null == _play) {
            _play = get(ENGINE_PLAYFRAMEWORK);
        }
        return _play;
    }

    private Boolean _logRenderTime = null;

    /**
     * Return {@link RythmConfigurationKey#LOG_TIME_RENDER_ENABLED} without
     * look up
     *
     * @return true if enable log render time
     */
    public boolean logRenderTime() {
        if (null == _logRenderTime) {
            _logRenderTime = get(LOG_TIME_RENDER_ENABLED);
        }
        return _logRenderTime;
    }

    private Boolean _loadPrecompiled = null;

    /**
     * Return {@link RythmConfigurationKey#ENGINE_LOAD_PRECOMPILED_ENABLED}
     * without lookup
     *
     * @return true if load precompiled
     */
    public boolean loadPrecompiled() {
        if (null == _loadPrecompiled) {
            Boolean b = get(ENGINE_LOAD_PRECOMPILED_ENABLED);
            _loadPrecompiled = b || gae();
        }
        return _loadPrecompiled;
    }

    private Boolean _precompileMode = null;

    /**
     * Return {@link RythmConfigurationKey#ENGINE_PRECOMPILE_MODE} without lookup
     *
     * @return true if precompiling
     */
    public boolean precompileMode() {
        if (null == _precompileMode) {
            _precompileMode = get(ENGINE_PRECOMPILE_MODE);
        }
        return _precompileMode;
    }

    private Boolean _disableFileWrite = null;

    /**
     * Return inversed value of {@link RythmConfigurationKey#ENGINE_FILE_WRITE_ENABLED}
     * without lookup
     *
     * @return true if file write is disabled
     */
    public boolean disableFileWrite() {
        if (null == _disableFileWrite) {
            boolean b = (Boolean) get(ENGINE_FILE_WRITE_ENABLED);
            b = b && !gae();
            _disableFileWrite = !b;
        }
        return _disableFileWrite;
    }

    private Boolean _gae = null;

    private static boolean isGaeSdkInClreplacedpath() {
        try {
            Clreplaced.forName("com.google.appengine.api.LifecycleManager");
            return true;
        } catch (Throwable t) {
        // Nothing to do
        }
        return false;
    }

    public boolean gae() {
        if (null == _gae) {
            boolean b = isGaeSdkInClreplacedpath();
            if (b) {
                try {
                    Clreplaced clz = Clreplaced.forName("org.rythmengine.conf.GAEDetectorImpl");
                    GAEDetector detector = (GAEDetector) clz.newInstance();
                    b = detector.isInGaeCloud();
                } catch (Throwable t) {
                    logger.warn(t, "error detecting gae environment");
                    b = false;
                }
            }
            _gae = b;
        }
        return _gae;
    }

    private Set<String> _restrictedClreplacedes = null;

    /**
     * Return {@link RythmConfigurationKey#SANDBOX_RESTRICTED_CLreplaced} without lookup
     * <p/>
     * <p>Note, the return value also contains rythm's built-in restricted clreplacedes</p>
     *
     * @return a set of restricted clreplacedes
     */
    public Set<String> restrictedClreplacedes() {
        if (null == _restrictedClreplacedes) {
            String s = get(SANDBOX_RESTRICTED_CLreplaced);
            s += ";org.rythmengine.Rythm;RythmEngine;RythmSecurityManager,java.io;java.nio;java.security;java.rmi;java.net;java.awt;java.applet";
            _restrictedClreplacedes = new HashSet<String>();
            for (String cls : Arrays.asList(s.split(";"))) {
                cls = cls.trim();
                if ("".equals(cls)) {
                    continue;
                }
                _restrictedClreplacedes.add(cls);
            }
        }
        return new HashSet<String>(_restrictedClreplacedes);
    }

    private Boolean _enableTypeInference = null;

    /**
     * Get {@link RythmConfigurationKey#FEATURE_TYPE_INFERENCE_ENABLED} without
     * lookup
     *
     * @return true if type inference is enabled
     */
    public boolean typeInferenceEnabled() {
        if (null == _enableTypeInference) {
            _enableTypeInference = get(FEATURE_TYPE_INFERENCE_ENABLED);
        }
        return _enableTypeInference;
    }

    private Boolean _smartEscapeEnabled = null;

    /**
     * Get {@link RythmConfigurationKey#FEATURE_SMART_ESCAPE_ENABLED} without lookup
     *
     * @return true if smart escape is enabled
     */
    public boolean smartEscapeEnabled() {
        if (null == _smartEscapeEnabled) {
            _smartEscapeEnabled = (Boolean) get(FEATURE_SMART_ESCAPE_ENABLED);
        }
        return _smartEscapeEnabled;
    }

    private Boolean _naturalTemplateEnabled = null;

    /**
     * Get {@link RythmConfigurationKey#FEATURE_NATURAL_TEMPLATE_ENABLED} without lookup
     *
     * @return true if natural template is enabled
     */
    public boolean naturalTemplateEnabled() {
        if (null == _naturalTemplateEnabled) {
            _naturalTemplateEnabled = (Boolean) get(FEATURE_NATURAL_TEMPLATE_ENABLED);
        }
        return _naturalTemplateEnabled;
    }

    private Boolean _debugJavaSourceEnabled = null;

    /**
     * Get {@link RythmConfigurationKey#ENGINE_OUTPUT_JAVA_SOURCE_ENABLED} without lookup
     *
     * @return true if debug java source is enabled
     */
    public boolean debugJavaSourceEnabled() {
        if (null == _debugJavaSourceEnabled) {
            _debugJavaSourceEnabled = (Boolean) get(ENGINE_OUTPUT_JAVA_SOURCE_ENABLED);
        }
        return _debugJavaSourceEnabled;
    }

    private Boolean _cacheEnabled = null;

    /**
     * Return true if cache is not disabled for the engine instance. A cache is disabled when
     * <ul>
     * <li>{@link RythmConfigurationKey#CACHE_ENABLED} is <code>true</code> or</li>
     * <li>{@link RythmConfigurationKey#CACHE_PROD_ONLY_ENABLED} is <code>true</code> and
     * {@link RythmConfigurationKey#ENGINE_MODE} is {@link org.rythmengine.Rythm.Mode#dev}</li>
     * </ul>
     *
     * @return true if cache enabled
     */
    public boolean cacheEnabled() {
        if (this == EMPTY_CONF)
            return false;
        if (null == _cacheEnabled) {
            Boolean ce = get(CACHE_ENABLED);
            if (!ce) {
                _cacheEnabled = false;
            } else {
                if (engine.isProdMode()) {
                    _cacheEnabled = true;
                } else {
                    Boolean po = get(CACHE_PROD_ONLY_ENABLED);
                    _cacheEnabled = !po;
                }
            }
        }
        return _cacheEnabled;
    }

    /**
     * Return true if cache is disabled for the engine instance.
     *
     * @return false if cache enabled
     * @see #cacheEnabled()
     */
    public boolean cacheDisabled() {
        return !cacheEnabled();
    }

    private Boolean _transformEnabled = null;

    /**
     * Return {@link RythmConfigurationKey#FEATURE_TRANSFORM_ENABLED} without look up
     *
     * @return true if transform enabled
     */
    public boolean transformEnabled() {
        if (null == _transformEnabled) {
            _transformEnabled = get(FEATURE_TRANSFORM_ENABLED);
        }
        return _transformEnabled;
    }

    private Boolean _compactEnabled = null;

    /**
     * Return {@link RythmConfigurationKey#CODEGEN_COMPACT_ENABLED} without look up
     *
     * @return true if compact mode is enabled
     */
    public boolean compactModeEnabled() {
        if (null == _compactEnabled) {
            _compactEnabled = get(CODEGEN_COMPACT_ENABLED);
        }
        return _compactEnabled;
    }

    private IDurationParser _durationParser = null;

    /**
     * Return {@link RythmConfigurationKey#CACHE_DURATION_PARSER_IMPL} without lookup
     *
     * @return the duration parser implementation
     */
    public IDurationParser durationParser() {
        if (null == _durationParser) {
            _durationParser = get(CACHE_DURATION_PARSER_IMPL);
        }
        return _durationParser;
    }

    private ICodeType _defaultCodeType = null;

    /**
     * Return {@link RythmConfigurationKey#DEFAULT_CODE_TYPE_IMPL} without lookup
     *
     * @return default code type
     */
    public ICodeType defaultCodeType() {
        if (null == _defaultCodeType) {
            _defaultCodeType = get(DEFAULT_CODE_TYPE_IMPL);
        }
        return _defaultCodeType;
    }

    private File _tmpDir = null;

    /**
     * Return {@link RythmConfigurationKey#HOME_TMP} without lookup
     *
     * @return temp dir
     */
    public File tmpDir() {
        if (null == _tmpDir) {
            URI uri = get(HOME_TMP);
            _tmpDir = new File(uri.getPath());
        }
        return _tmpDir;
    }

    private List<URI> _templateHome = null;

    /**
     * Return {@link RythmConfigurationKey#HOME_TEMPLATE} without lookup
     *
     * @return template home
     */
    public List<URI> templateHome() {
        if (null == _templateHome) {
            Object o = get(RythmConfigurationKey.HOME_TEMPLATE);
            if (o instanceof URI) {
                _templateHome = Arrays.asList(new URI[] { (URI) o });
            } else if (o instanceof List) {
                _templateHome = (List<URI>) o;
            } else if (o instanceof File) {
                File root = (File) o;
                _templateHome = Arrays.asList(new URI[] { root.toURI() });
            }
        }
        return _templateHome;
    }

    /**
     * Set template source home path
     * <p/>
     * <p><b>Note</b>, this is not supposed to be used by user application or third party plugin</p>
     */
    public void setTemplateHome(File home) {
        raw.put(HOME_TEMPLATE.getKey(), home);
        data.put(HOME_TEMPLATE, home);
    }

    private IByteCodeEnhancer _byteCodeEnhancer = IByteCodeEnhancer.INSTS.NULL;

    /**
     * Return {@link RythmConfigurationKey#CODEGEN_BYTE_CODE_ENHANCER} without lookup
     *
     * @return the byte code enhancer implementation
     */
    public IByteCodeEnhancer byteCodeEnhancer() {
        if (IByteCodeEnhancer.INSTS.NULL == _byteCodeEnhancer) {
            _byteCodeEnhancer = get(CODEGEN_BYTE_CODE_ENHANCER);
        }
        return _byteCodeEnhancer;
    }

    private ISourceCodeEnhancer _srcEnhancer = null;

    public ISourceCodeEnhancer sourceEnhancer() {
        if (null == _srcEnhancer) {
            _srcEnhancer = get(CODEGEN_SOURCE_CODE_ENHANCER);
        }
        return _srcEnhancer;
    }

    private Locale _locale = null;

    /**
     * Get {@link RythmConfigurationKey#I18N_LOCALE} without lookup
     *
     * @return locale
     */
    public Locale locale() {
        if (null == _locale) {
            _locale = get(I18N_LOCALE);
        }
        return _locale;
    }

    private List<String> _messageSources = null;

    /**
     * Get {@link RythmConfigurationKey#I18N_MESSAGE_SOURCES} without lookup
     */
    public List<String> messageSources() {
        if (null == _messageSources) {
            _messageSources = Arrays.asList(get(I18N_MESSAGE_SOURCES).toString().split("[, \\t]+"));
        }
        return _messageSources;
    }

    private II18nMessageResolver _i18n = null;

    /**
     * Get {@link RythmConfigurationKey#I18N_MESSAGE_RESOLVER} without lookup
     */
    public II18nMessageResolver i18nMessageResolver() {
        if (null == _i18n) {
            _i18n = get(I18N_MESSAGE_RESOLVER);
        }
        return _i18n;
    }

    private String _suffix = null;

    /**
     * Get {@link RythmConfigurationKey#RESOURCE_NAME_SUFFIX} without lookup
     */
    public String resourceNameSuffix() {
        if (null == _suffix) {
            _suffix = get(RESOURCE_NAME_SUFFIX);
        }
        return _suffix;
    }

    private Integer _resourceRefreshInterval = null;

    /**
     * Get {@link RythmConfigurationKey#RESOURCE_REFRESH_INTERVAL}
     * @return the key for the resourceRefreshInterval
     */
    public long resourceRefreshInterval() {
        if (null == _resourceRefreshInterval) {
            _resourceRefreshInterval = get(RESOURCE_REFRESH_INTERVAL);
        }
        return _resourceRefreshInterval.longValue();
    }

    private Boolean _autoScan = null;

    public boolean autoScan() {
        if (null == _autoScan) {
            _autoScan = get(RESOURCE_AUTO_SCAN);
        }
        return _autoScan;
    }

    private String _allowedSysProps = null;

    public String allowedSystemProperties() {
        if (null == _allowedSysProps) {
            _allowedSysProps = get(SANDBOX_ALLOWED_SYSTEM_PROPERTIES);
        }
        return _allowedSysProps;
    }

    private Boolean _sandboxTmpIO = null;

    public boolean sandboxTmpIO() {
        if (null == _sandboxTmpIO) {
            _sandboxTmpIO = get(SANDBOX_TEMP_IO_ENABLED);
        }
        return _sandboxTmpIO;
    }

    private Boolean _hasGlobalInclude = null;

    public boolean hasGlobalInclude() {
        if (engine.insideSandbox())
            return false;
        if (null == _hasGlobalInclude) {
            ITemplateResource rsrc = engine.resourceManager().getResource("__global.rythm");
            _hasGlobalInclude = rsrc.isValid();
        }
        return _hasGlobalInclude;
    }

    public static final RythmConfiguration EMPTY_CONF = new RythmConfiguration(Collections.<String, Object>emptyMap(), null);

    /**
     * Return <tt>RythmConfiguration</tt> instance of current RythmEngine, or
     * if it is not inside a RythmEngine runtime context, an {@link #EMPTY_CONF empty configuration}
     * is returned
     *
     * @return the configuration instance replacedociated with engine running in the current thread
     */
    public static RythmConfiguration get() {
        RythmEngine engine = RythmEngine.get();
        return null != engine ? engine.conf() : EMPTY_CONF;
    }

    private final static ILogger logger = Logger.get(RythmConfiguration.clreplaced);

    public void debug() {
        logger.info("start to dump rythm configuration >>>");
        for (RythmConfigurationKey k : RythmConfigurationKey.values()) {
            logger.info("%s: %s", k, get(k));
        }
        logger.info("end dumping rythm configuration <<<");
    }
}

18 View Complete Implementation : TemplateParser.java
Copyright Apache License 2.0
Author : rythmengine
public clreplaced TemplateParser implements IContext {

    private final static ILogger logger = Logger.get(TemplateParser.clreplaced);

    private final CodeBuilder cb;

    private final RythmEngine engine;

    private final RythmConfiguration conf;

    private final boolean compactMode;

    private String template;

    private int totalLines;

    int cursor = 0;

    public TemplateParser(CodeBuilder cb) {
        this.template = cb.template();
        totalLines = StringUtils.countMatches(template, "\n") + 1;
        this.cb = cb;
        this.engine = cb.engine();
        this.conf = this.engine.conf();
        this.compactMode = this.conf.compactModeEnabled();
        pushCodeType(cb.templateDefLang);
    }

    public static clreplaced ExitInstruction extends FastRuntimeException {
    }

    private static abstract clreplaced RewindableException extends ParseException {

        public RewindableException(IContext ctx, String msg, Object... args) {
            super(ctx.getEngine(), ctx.getTemplateClreplaced(), ctx.currentLine(), msg, args);
        }
    }

    public static clreplaced NoFreeLoopException extends RewindableException {

        public NoFreeLoopException(IContext ctx) {
            super(ctx, "Free loop style (@for(;;)) not allowed in current dialect[%s]", ctx.getDialect());
        }
    }

    public static clreplaced ScriptingDisabledException extends RewindableException {

        public ScriptingDisabledException(IContext ctx) {
            super(ctx, "Scripting not allowed in current dialect[%s]", ctx.getDialect());
        }
    }

    public static clreplaced ComplexExpressionException extends RewindableException {

        public ComplexExpressionException(IContext ctx) {
            super(ctx, "Complex expression not allowed in current dialect[%s]", ctx.getDialect());
        }
    }

    public static clreplaced TypeDeclarationException extends RewindableException {

        public TypeDeclarationException(IContext ctx) {
            super(ctx, "Type declaration not allowed in current dialect[%s]", ctx.getDialect());
        }
    }

    void parse() {
        DialectManager dm = engine.dialectManager();
        while (true) {
            this.breakStack.clear();
            this.codeTypeStack.clear();
            this.pushCodeType(cb.templateDefLang);
            this.inBodyStack.clear();
            this.inBodyStack2.clear();
            this.compactStack.clear();
            this.continueStack.clear();
            this.localeStack.clear();
            this.insideDirectiveComment = false;
            this.blocks.clear();
            cursor = 0;
            cb.rewind();
            dm.beginParse(this);
            TemplateResourceManager.setUpTmpBlackList();
            try {
                TemplateTokenizer tt = new TemplateTokenizer(this);
                for (Token builder : tt) {
                    cb.addBuilder(builder);
                }
                dm.endParse(this);
                break;
            } catch (ExitInstruction e) {
                dm.endParse(this);
                break;
            } catch (RewindableException e) {
                dm.endParse(this);
                if (null != cb.requiredDialect) {
                    throw e;
                }
            } catch (RuntimeException e) {
                dm.endParse(this);
                throw e;
            }
        }
    }

    @Override
    public TemplateClreplaced getTemplateClreplaced() {
        return cb.getTemplateClreplaced();
    }

    @Override
    public CodeBuilder getCodeBuilder() {
        return cb;
    }

    private IDialect dialect = null;

    public IDialect getDialect() {
        return dialect;
    }

    public void setDialect(IDialect dialect) {
        this.dialect = dialect;
    }

    @Override
    public String getRemain() {
        return cursor < template.length() ? template.substring(cursor) : "";
    }

    @Override
    public int cursor() {
        return cursor;
    }

    @Override
    public boolean hasRemain() {
        return cursor < template.length();
    }

    @Override
    public char peek() {
        if (!hasRemain())
            return '\u0000';
        return template.charAt(cursor);
    }

    @Override
    public char pop() {
        if (!hasRemain())
            throw new ArrayIndexOutOfBoundsException();
        char c = template.charAt(cursor);
        step(1);
        return c;
    }

    @Override
    public void step(int i) {
        cursor += i;
    }

    @Override
    public String getTemplateSource(int start, int end) {
        return template.substring(start, end);
    }

    private Stack<IBlockHandler> blocks = new Stack<IBlockHandler>();

    @Override
    public void openBlock(IBlockHandler bh) {
        bh.openBlock();
        blocks.push(bh);
    }

    @Override
    public IBlockHandler currentBlock() {
        return blocks.isEmpty() ? null : blocks.peek();
    }

    @Override
    public String closeBlock() throws ParseException {
        if (blocks.isEmpty())
            throw new ParseException(getEngine(), cb.getTemplateClreplaced(), currentLine(), "No open block found");
        IBlockHandler bh = blocks.pop();
        return null == bh ? "" : bh.closeBlock();
    }

    @Override
    public String currentSection() {
        int len = blocks.size();
        for (int i = len - 1; i >= 0; --i) {
            IBlockHandler h = blocks.get(i);
            if (h instanceof SectionParser.SectionToken) {
                return ((SectionParser.SectionToken) h).section();
            }
        }
        return null;
    }

    @Override
    public int currentLine() {
        // for testing purpose only
        if (null == template)
            return -1;
        if (cursor >= template.length())
            return totalLines;
        // return template.substring(0, cursor).split("(\\r\\n|\\n|\\r)").length;
        return StringUtils.countMatches(template.substring(0, cursor), "\n") + 1;
    }

    @Override
    public RythmEngine getEngine() {
        return engine;
    }

    @Override
    public boolean compactMode() {
        if (!compactStack.empty())
            return compactStack.peek();
        return compactMode;
    }

    private Stack<Boolean> compactStack = new Stack<Boolean>();

    @Override
    public void pushCompact(Boolean compact) {
        compactStack.push(compact);
    }

    @Override
    public Boolean peekCompact() {
        if (compactStack.empty())
            return null;
        return compactStack.peek();
    }

    @Override
    public Boolean popCompact() {
        if (compactStack.empty())
            return null;
        return compactStack.pop();
    }

    private Stack<Break> breakStack = new Stack<Break>();

    @Override
    public void pushBreak(Break b) {
        breakStack.push(b);
    }

    @Override
    public Break peekBreak() {
        if (breakStack.empty())
            return null;
        return breakStack.peek();
    }

    @Override
    public Break popBreak() {
        if (breakStack.empty())
            return null;
        return breakStack.pop();
    }

    private Stack<Continue> continueStack = new Stack<Continue>();

    @Override
    public void pushContinue(Continue b) {
        continueStack.push(b);
    }

    @Override
    public Continue peekContinue() {
        if (continueStack.empty())
            return null;
        return continueStack.peek();
    }

    @Override
    public Continue popContinue() {
        if (continueStack.empty())
            return null;
        return continueStack.pop();
    }

    @Override
    public boolean insideBody() {
        if (!inBodyStack.empty())
            return inBodyStack.peek();
        return false;
    }

    private Stack<Boolean> inBodyStack = new Stack<Boolean>();

    @Override
    public void pushInsideBody(Boolean b) {
        inBodyStack.push(b);
    }

    @Override
    public Boolean peekInsideBody() {
        if (inBodyStack.empty())
            return false;
        return inBodyStack.peek();
    }

    @Override
    public Boolean popInsideBody() {
        if (inBodyStack.empty())
            return null;
        return inBodyStack.pop();
    }

    @Override
    public boolean insideBody2() {
        if (!inBodyStack2.empty())
            return inBodyStack2.peek();
        return false;
    }

    private Stack<Boolean> inBodyStack2 = new Stack<Boolean>();

    @Override
    public void pushInsideBody2(Boolean b) {
        inBodyStack2.push(b);
    }

    @Override
    public Boolean peekInsideBody2() {
        if (inBodyStack2.empty())
            return false;
        return inBodyStack2.peek();
    }

    @Override
    public Boolean popInsideBody2() {
        if (inBodyStack2.empty())
            return null;
        return inBodyStack2.pop();
    }

    private boolean insideDirectiveComment = false;

    @Override
    public boolean insideDirectiveComment() {
        return this.insideDirectiveComment;
    }

    @Override
    public void enterDirectiveComment() {
        insideDirectiveComment = true;
    }

    @Override
    public void leaveDirectiveComment() {
        insideDirectiveComment = false;
    }

    private Stack<ICodeType> codeTypeStack = new Stack<ICodeType>();

    @Override
    public ICodeType peekCodeType() {
        if (codeTypeStack.isEmpty())
            return null;
        return codeTypeStack.peek();
    }

    @Override
    public void pushCodeType(ICodeType type) {
        ICodeType cur = peekCodeType();
        if (null != cur) {
            type.setParent(cur);
        }
        codeTypeStack.push(type);
    }

    @Override
    public ICodeType popCodeType() {
        ICodeType cur = peekCodeType();
        if (null == cur) {
            return null;
        }
        cur.setParent(null);
        codeTypeStack.pop();
        return cur;
    }

    private Stack<Locale> localeStack = new Stack<Locale>();

    @Override
    public Locale peekLocale() {
        return localeStack.isEmpty() ? null : localeStack.peek();
    }

    @Override
    public void pushLocale(Locale locale) {
        localeStack.push(locale);
    }

    @Override
    public Locale popLocale() {
        return localeStack.isEmpty() ? null : localeStack.pop();
    }

    public void shutdown() {
        dialect = null;
    }

    /* this constructor is just for testing purpose */
    private TemplateParser(String s) {
        template = s;
        totalLines = template.split("(\\r\\n|\\n|\\r)").length + 1;
        cb = null;
        engine = null;
        conf = null;
        compactMode = true;
    }
}

18 View Complete Implementation : CacheKey.java
Copyright Apache License 2.0
Author : rythmengine
public static String i18nBundle(RythmEngine engine, Locale locale) {
    return String.format("i18nB-%s-%s", locale, engine);
}

18 View Complete Implementation : ParamTypeInferencer.java
Copyright Apache License 2.0
Author : rythmengine
public static void registerParams(RythmEngine engine, Object... args) {
    if (!engine.conf().typeInferenceEnabled())
        return;
    if (null == args || args.length == 0)
        return;
    Map<String, String> tMap = typeMap.get();
    tMap.clear();
    long id = 0;
    if (args.length == 1 && args[0] instanceof Map) {
        Map<String, Object> params = (Map) args[0];
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            Object val = entry.getValue();
            String typeName = getTypeName(val);
            tMap.put(entry.getKey(), typeName);
            id += typeName.hashCode() * entry.getKey().hashCode();
        }
    } else {
        // suppose template variable is denoted with @1, @2 ...
        for (int i = 0; i < args.length; ++i) {
            // start from 1 instead of 0
            String name = "__v_" + (i + 1);
            String typeName = getTypeName(args[i]);
            tMap.put(name, typeName);
            id += (i + 1) * typeName.hashCode();
        }
    }
    if (id < 0)
        id = -1 * id;
    uuid.set(String.valueOf(id));
}

18 View Complete Implementation : TemplateResourceBase.java
Copyright Apache License 2.0
Author : rythmengine
@Override
public ICodeType codeType(RythmEngine engine) {
    Object key = getKey();
    String s = S.str(key);
    return getTypeOfPath(engine, s);
}

18 View Complete Implementation : RythmView.java
Copyright Apache License 2.0
Author : actframework
public RythmEngine getEngine(App app) {
    RythmEngine engine = engines.get(app);
    if (null == engine) {
        RythmEngine newEngine = createEngine(app);
        engine = engines.putIfAbsent(app, newEngine);
        if (null == engine) {
            engine = newEngine;
        } else {
            newEngine.shutdown();
        }
    }
    return engine;
}

18 View Complete Implementation : TemplateClass.java
Copyright Apache License 2.0
Author : rythmengine
private ITemplate templateInstance_(RythmEngine engine) {
    if (!isValid) {
        return NULL_TEMPLATE;
    }
    if (null == templateInstance) {
        try {
            Clreplaced<?> clz = loadJavaClreplaced();
            TemplateBase tmpl = (TemplateBase) clz.newInstance();
            tmpl.__setTemplateClreplaced(this);
            engine.registerTemplate(tmpl);
            // engine.registerTemplate(getFullName(true), tmpl);
            templateInstance = tmpl;
        } catch (RythmException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("Error load template instance for " + getKey(), e);
        }
    }
    if (!engine.isProdMode()) {
        engine.registerTemplate(templateInstance);
        // check parent clreplaced change
        Clreplaced<?> c = templateInstance.getClreplaced();
        Clreplaced<?> pc = c.getSuperclreplaced();
        if (null != pc && !Modifier.isAbstract(pc.getModifiers())) {
            engine.clreplacedes().getByClreplacedName(pc.getName());
        }
    }
    return templateInstance;
}

18 View Complete Implementation : TemplateClassCache.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Used to speed up compilation time
 */
public clreplaced TemplateClreplacedCache {

    private static final ILogger logger = Logger.get(TemplateClreplacedCache.clreplaced);

    private final RythmEngine engine;

    private final RythmConfiguration conf;

    private final Rythm.Mode mode;

    public TemplateClreplacedCache(RythmEngine engine) {
        if (null == engine)
            throw new NullPointerException();
        this.engine = engine;
        this.conf = engine.conf();
        this.mode = engine.mode();
    }

    private boolean readEnabled() {
        return (mode.isDev() || conf.loadPrecompiled()) && !RythmEngine.insideSandbox();
    }

    private boolean writeEnabled() {
        return (mode.isDev() || !conf.disableFileWrite() || conf.precompileMode()) && !RythmEngine.insideSandbox();
    }

    /**
     * Delete the bytecode
     *
     * @param tc The template clreplaced
     */
    public void deleteCache(TemplateClreplaced tc) {
        if (!writeEnabled())
            return;
        try {
            File f = getCacheFile(tc);
            if (f.exists() && !f.delete()) {
                f.deleteOnExit();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Retrieve java source and bytecode if template content has not changed
     *
     * @param tc
     */
    public void loadTemplateClreplaced(TemplateClreplaced tc) {
        if (!readEnabled()) {
            return;
        }
        InputStream is = null;
        try {
            File f = getCacheFile(tc);
            if (!f.exists() || !f.canRead())
                return;
            is = new BufferedInputStream(new FileInputStream(f));
            // --- check hash
            int offset = 0;
            int read;
            StringBuilder hash = new StringBuilder();
            while ((read = is.read()) != 0) {
                if (read == -1) {
                    logger.error("Failed to read cache file for template clreplaced: %s", tc);
                    return;
                }
                hash.append((char) read);
                offset++;
            }
            // check hash only in non precompiled mode
            if (!conf.loadPrecompiled()) {
                String curHash = hash(tc);
                if (!curHash.equals(hash.toString())) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Bytecode too old (%s != %s)", hash, curHash);
                    }
                    return;
                }
            }
            // --- load java source
            read = -1;
            StringBuilder source = new StringBuilder();
            while ((read = is.read()) != 0) {
                source.append((char) read);
                offset++;
            }
            if (source.length() != 0) {
                String s = source.toString();
                String[] sa = s.split("__INCLUDED_TAG_TYPES__");
                tc.javaSource = sa[0];
                s = sa[1];
                sa = s.split("__INCULDED_TEMPLATE_CLreplaced_NAME_LIST__");
                tc.deserializeIncludeTagTypes(sa[0]);
                s = sa[1];
                sa = s.split("__IMPORT_PATH_LIST__");
                tc.setIncludeTemplateClreplacedNames(sa[0]);
                if (sa.length > 1) {
                    s = sa[1];
                    sa = s.split(";");
                    Set<String> importPaths = new HashSet<String>();
                    for (String path : sa) {
                        if ("java.lang".equals(path))
                            continue;
                        importPaths.add(path);
                    }
                    tc.replaceImportPath(importPaths);
                }
            }
            // else it must be an inner clreplaced
            // --- load byte code
            byte[] byteCode = new byte[(int) f.length() - (offset + 2)];
            is.read(byteCode);
            tc.loadCachedByteCode(byteCode);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (is != null)
                try {
                    is.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
        }
    }

    public void cacheTemplateClreplacedSource(TemplateClreplaced tc) {
        if (!writeEnabled()) {
            return;
        }
        try {
            File f = getCacheSourceFile(tc);
            OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
            os.write(tc.javaSource.getBytes("utf-8"));
            os.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void cacheTemplateClreplaced(TemplateClreplaced tc) {
        if (!writeEnabled()) {
            return;
        }
        String hash = hash(tc);
        try {
            File f = getCacheFile(tc);
            // --- write hash value
            OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
            os.write(hash.getBytes("utf-8"));
            // --- cache java source
            os.write(0);
            if (null != tc.javaSource) {
                TextBuilder tb = new TextBuilder();
                tb.p(tc.javaSource);
                tb.p("__INCLUDED_TAG_TYPES__").p(tc.serializeIncludeTagTypes());
                tb.p("__INCULDED_TEMPLATE_CLreplaced_NAME_LIST__").p(tc.refreshIncludeTemplateClreplacedNames()).p("__IMPORT_PATH_LIST__");
                if (tc.importPaths == null) {
                    tc.importPaths = new HashSet<String>(0);
                }
                if (tc.importPaths.isEmpty()) {
                    tc.importPaths.add("java.lang");
                }
                boolean first = true;
                for (String s : tc.importPaths) {
                    if (!first) {
                        tb.p(";");
                    } else {
                        first = false;
                    }
                    tb.p(s);
                }
                os.write(tb.toString().getBytes("utf-8"));
            }
            // else the tc is an inner clreplaced thus we don't have javaSource at all
            // --- cache byte code
            os.write(0);
            // if (null != tc.enhancedByteCode) {
            os.write(tc.enhancedByteCode);
            os.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Build a hash of the source code.
     * To efficiently track source code modifications.
     */
    String hash(TemplateClreplaced tc) {
        try {
            // Object enhancer = engine.conf().byteCodeEnhancer();
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update((engine.version() + tc.getTemplateSource(true)).getBytes("utf-8"));
            byte[] digest = messageDigest.digest();
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < digest.length; ++i) {
                int value = digest[i];
                if (value < 0) {
                    value += 256;
                }
                builder.append(Integer.toHexString(value));
            }
            return builder.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    String cacheFileName(TemplateClreplaced tc, String suffix) {
        return tc.name0() + suffix;
    }

    private File getCacheFile(String fileName) {
        RythmConfiguration conf = engine.conf();
        if (conf.loadPrecompiled() || conf.precompileMode()) {
            URI uri = conf.get(RythmConfigurationKey.HOME_PRECOMPILED);
            File precompileDir = new File(uri);
            return new File(precompileDir, fileName);
        } else {
            File f = new File(conf.tmpDir(), fileName);
            return f;
        }
    }

    /**
     * Retrieve the real file that will be used as cache.
     */
    File getCacheFile(TemplateClreplaced tc) {
        String id = cacheFileName(tc, ".rythm");
        return getCacheFile(id);
    }

    File getCacheSourceFile(TemplateClreplaced tc) {
        String id = cacheFileName(tc, ".java");
        return getCacheFile(id);
    }
}

18 View Complete Implementation : Gh170Helper.java
Copyright Apache License 2.0
Author : rythmengine
public static void main(String[] args) throws Exception {
    final RythmEngine engine = prepareEngine();
    System.out.println(engine.mode());
    prepareTmpl();
    System.out.println(engine.render(TMPL_NAME, "world"));
}

18 View Complete Implementation : WordprocessingMLRythmTemplate.java
Copyright Apache License 2.0
Author : hiwepy
/**
 * 该模板仅负责使用Rythm模板引擎将指定模板生成HTML并将HTML转换成XHTML后,作为模板生成WordprocessingMLPackage对象
 * @author <a href="https://github.com/hiwepy">hiwepy</a>
 */
public clreplaced WordprocessingMLRythmTemplate extends WordprocessingMLTemplate {

    protected RythmEngine engine;

    protected WordprocessingMLHtmlTemplate mlHtmlTemplate;

    public WordprocessingMLRythmTemplate() {
        this(false, false);
    }

    public WordprocessingMLRythmTemplate(boolean landscape, boolean altChunk) {
        this.mlHtmlTemplate = new WordprocessingMLHtmlTemplate(landscape, altChunk);
    }

    public WordprocessingMLRythmTemplate(WordprocessingMLHtmlTemplate template) {
        this.mlHtmlTemplate = template;
    }

    /**
     * 使用Rythm模板引擎渲染模板
     * @param template :模板内容
     * @param variables :变量
     * @return {@link WordprocessingMLPackage} 对象
     * @throws Exception :异常对象
     */
    @Override
    public WordprocessingMLPackage process(String template, Map<String, Object> variables) throws Exception {
        // 创建模板输出内容接收对象
        StringWriter output = new StringWriter();
        // 使用Rythm模板引擎渲染模板
        getEngine().getTemplate(template, variables).render(output);
        // 获取模板渲染后的结果
        String html = output.toString();
        // 使用HtmlTemplate进行渲染
        return mlHtmlTemplate.process(html, variables);
    }

    public RythmEngine getEngine() throws IOException {
        return engine == null ? getInternalEngine() : engine;
    }

    public void setEngine(RythmEngine engine) {
        this.engine = engine;
    }

    protected synchronized RythmEngine getInternalEngine() throws IOException {
        Properties props = ConfigUtils.filterWithPrefix("docx4j.rythm.", "docx4j.rythm.", Docx4jProperties.getProperties(), false);
        props.put("engine.mode", Rythm.Mode.valueOf(props.getProperty("engine.mode", "dev")));
        props.put("log.enabled", false);
        props.put("feature.smart_escape.enabled", false);
        props.put("feature.transform.enabled", false);
        try {
            props.put("home.template", Rythm.clreplaced.getResource(props.getProperty("home.template")).toURI().toURL().getFile());
        } catch (URISyntaxException e) {
            // ignore
            props.put("home.tmp", "/");
        }
        props.put("codegen.dynamic_exp.enabled", true);
        props.put("built_in.code_type", "false");
        props.put("built_in.transformer", "false");
        props.put("engine.file_write", "false");
        props.put("codegen.compact.enabled", "false");
        RythmEngine engine = new RythmEngine(props);
        // 设置模板引擎,减少重复初始化消耗
        this.setEngine(engine);
        return engine;
    }
}

18 View Complete Implementation : TemplateClassLoader.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Created by IntelliJ IDEA.
 * User: luog
 * Date: 18/01/12
 * Time: 9:01 PM
 * To change this template use File | Settings | File Templates.
 */
public clreplaced TemplateClreplacedLoader extends ClreplacedLoader {

    private static final ILogger logger = Logger.get(TemplateClreplaced.clreplaced);

    public static clreplaced ClreplacedStateHashCreator {

        private final Pattern clreplacedDefFinderPattern = Pattern.compile("\\s+clreplaced\\s([a-zA-Z0-9_]+)\\s+");

        private static clreplaced FileWithClreplacedDefs {

            private final File file;

            private final long size;

            private final long lastModified;

            private final String clreplacedDefs;

            private FileWithClreplacedDefs(File file, String clreplacedDefs) {
                this.file = file;
                this.clreplacedDefs = clreplacedDefs;
                // store size and time for this file..
                size = file.length();
                lastModified = file.lastModified();
            }

            /**
             * @return true if file has changed on disk
             */
            public boolean fileNotChanges() {
                return size == file.length() && lastModified == file.lastModified();
            }

            public String getClreplacedDefs() {
                return clreplacedDefs;
            }
        }

        private final Map<File, FileWithClreplacedDefs> clreplacedDefsInFileCache = new HashMap<File, FileWithClreplacedDefs>();

        public synchronized int computePathHash(File... paths) {
            StringBuilder buf = new StringBuilder();
            for (File file : paths) {
                scan(buf, file);
            }
            // TODO: should use better hashing-algorithm.. MD5? SHA1?
            // I think hashCode() has too many collisions..
            return buf.toString().hashCode();
        }

        private void scan(StringBuilder buf, File current) {
            if (!current.isDirectory()) {
                if (current.getName().endsWith(".java")) {
                    buf.append(getClreplacedDefsForFile(current));
                }
            } else if (!current.getName().startsWith(".")) {
                // TODO: we could later optimizie it further if we check if the entire folder is unchanged
                File[] fa = current.listFiles();
                if (null != fa) {
                    for (File file : current.listFiles()) {
                        scan(buf, file);
                    }
                }
            }
        }

        private String getClreplacedDefsForFile(File file) {
            FileWithClreplacedDefs fileWithClreplacedDefs = clreplacedDefsInFileCache.get(file);
            if (fileWithClreplacedDefs != null && fileWithClreplacedDefs.fileNotChanges()) {
                // found the file in cache and it has not changed on disk
                return fileWithClreplacedDefs.getClreplacedDefs();
            }
            // didn't find it or it has changed on disk
            // we must re-parse it
            StringBuilder buf = new StringBuilder();
            Matcher matcher = clreplacedDefFinderPattern.matcher(IO.readContentreplacedtring(file));
            buf.append(file.getName());
            buf.append("(");
            while (matcher.find()) {
                buf.append(matcher.group(1));
                buf.append(",");
            }
            buf.append(")");
            String clreplacedDefs = buf.toString();
            // store it in cache
            clreplacedDefsInFileCache.put(file, new FileWithClreplacedDefs(file, clreplacedDefs));
            return clreplacedDefs;
        }
    }

    private final ClreplacedStateHashCreator clreplacedStateHashCreator = new ClreplacedStateHashCreator();

    /**
     * Each unique instance of this clreplaced represent a State of the TemplateClreplacedLoader.
     * When some clreplacedCache is reloaded, them the TemplateClreplacedLoader get a new state.
     * <p/>
     * This makes it easy for other parts of Play to cache stuff based on the
     * the current State of the TemplateClreplacedLoader..
     * <p/>
     * They can store the reference to the current state, then later, before reading from cache,
     * they could check if the state of the TemplateClreplacedLoader has changed..
     */
    public static clreplaced TemplateClreplacedloaderState {

        private static AtomicLong nextStateValue = new AtomicLong();

        private final long currentStateValue = nextStateValue.getAndIncrement();

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClreplaced() != o.getClreplaced())
                return false;
            TemplateClreplacedloaderState that = (TemplateClreplacedloaderState) o;
            return (currentStateValue == that.currentStateValue);
        }

        @Override
        public int hashCode() {
            return (int) (currentStateValue ^ (currentStateValue >>> 32));
        }
    }

    /**
     * A representation of the current state of the TemplateClreplacedLoader.
     * It gets a new value each time the state of the clreplacedloader changes.
     */
    public TemplateClreplacedloaderState currentState = new TemplateClreplacedloaderState();

    /**
     * This protection domain applies to all loaded clreplacedCache.
     */
    public ProtectionDomain protectionDomain;

    public RythmEngine engine;

    private RythmConfiguration conf;

    private static ClreplacedLoader getDefParent(RythmEngine engine) {
        return engine.conf().get(RythmConfigurationKey.ENGINE_CLreplaced_LOADER_PARENT_IMPL);
    }

    public TemplateClreplacedLoader(RythmEngine engine) {
        this(getDefParent(engine), engine);
    }

    public TemplateClreplacedLoader(ClreplacedLoader parent, RythmEngine engine) {
        super(parent);
        this.engine = engine;
        this.conf = engine.conf();
        for (TemplateClreplaced tc : engine.clreplacedes().all()) {
            tc.uncompile();
        }
        pathHash = computePathHash();
    // try {
    // CodeSource codeSource = new CodeSource(new URL("file:" + Play.applicationPath.getAbsolutePath()), (Certificate[]) null);
    // Permissions permissions = new Permissions();
    // permissions.add(new AllPermission());
    // protectionDomain = new ProtectionDomain(codeSource, permissions);
    // } catch (MalformedURLException e) {
    // throw new UnexpectedException(e);
    // }
    }

    private static final ThreadLocal<String> sandboxPreplacedword = new ThreadLocal<String>();

    public static void setSandboxPreplacedword(String preplacedword) {
        sandboxPreplacedword.set(preplacedword);
    }

    @Override
    protected synchronized Clreplaced<?> loadClreplaced(String name, boolean resolve) throws ClreplacedNotFoundException {
        if (name.contains("UrlResolver")) {
            logger.info("loading UrlResovler...");
        }
        // init secure context for sandbox
        // SecurityManager sm;
        // RythmSecurityManager rsm = null;
        // String preplaced = null;
        try {
            if (Rythm.insideSandbox()) {
                if (conf.restrictedClreplacedes().contains(name)) {
                    throw new ClreplacedNotFoundException("Access to clreplaced " + name + " is restricted in sandbox mode");
                }
            // sm = System.getSecurityManager();
            // if (null != sm && sm instanceof RythmSecurityManager) {
            // rsm = (RythmSecurityManager) sm;
            // preplaced = sandboxPreplacedword.get();
            // }
            }
            TemplateClreplaced tc = engine.clreplacedes().clsNameIdx.get(name);
            if (null == tc) {
                // it's not a template clreplaced, let's try to find already loaded one
                Clreplaced<?> c = findLoadedClreplaced(name);
                if (c != null) {
                    return c;
                }
            }
            // First check if it's an application Clreplaced
            Clreplaced<?> TemplateClreplaced = loadTemplateClreplaced(name);
            if (TemplateClreplaced != null) {
                if (resolve) {
                    resolveClreplaced(TemplateClreplaced);
                }
                return TemplateClreplaced;
            }
            // Delegate to the clreplacedic clreplacedloader
            // boolean unlockSM = /*engine.isDevMode() && */null != rsm;
            // release sandbox preplacedword if running inside sandbox in order to load
            // application clreplacedes when running is dev mode
            // if (unlockSM) {
            // rsm.unlock(preplaced);
            // }
            return super.loadClreplaced(name, resolve);
        } finally {
        // if (unlockSM) {
        // rsm.lock(preplaced);
        // }
        }
    }

    @SuppressWarnings("unchecked")
    private Clreplaced<?> loadTemplateClreplaced(String name) {
        Clreplaced<?> maybeAlreadyLoaded = findLoadedClreplaced(name);
        if (maybeAlreadyLoaded != null) {
            return maybeAlreadyLoaded;
        }
        long start = System.currentTimeMillis();
        TemplateClreplaced templateClreplaced = engine.clreplacedes().getByClreplacedName(name);
        if (templateClreplaced != null) {
            if (templateClreplaced.isDefinable()) {
                return templateClreplaced.javaClreplaced;
            }
            // bCache.getBytecode(name, templateClreplaced.javaSource);
            byte[] bc = templateClreplaced.enhancedByteCode;
            if (!templateClreplaced.isClreplaced()) {
                definePackage(templateClreplaced.getPackage(), null, null, null, null, null, null, null);
            } else {
                loadPackage(name);
            }
            if (bc != null) {
                // templateClreplaced.enhancedByteCode = bc;
                templateClreplaced.javaClreplaced = (Clreplaced<ITemplate>) defineClreplaced(templateClreplaced.name(), templateClreplaced.enhancedByteCode, 0, templateClreplaced.enhancedByteCode.length, protectionDomain);
                resolveClreplaced(templateClreplaced.javaClreplaced);
                if (!templateClreplaced.isClreplaced()) {
                    templateClreplaced.javaPackage = templateClreplaced.javaClreplaced.getPackage();
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("%sms to load clreplaced %s from clsNameIdx", System.currentTimeMillis() - start, name);
                }
                return templateClreplaced.javaClreplaced;
            }
            if (templateClreplaced.javaByteCode != null || templateClreplaced.compile() != null) {
                templateClreplaced.enhance();
                templateClreplaced.javaClreplaced = (Clreplaced<ITemplate>) defineClreplaced(templateClreplaced.name(), templateClreplaced.enhancedByteCode, 0, templateClreplaced.enhancedByteCode.length, protectionDomain);
                resolveClreplaced(templateClreplaced.javaClreplaced);
                if (!templateClreplaced.isClreplaced()) {
                    templateClreplaced.javaPackage = templateClreplaced.javaClreplaced.getPackage();
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("%sms to load clreplaced %s", System.currentTimeMillis() - start, name);
                }
                return templateClreplaced.javaClreplaced;
            }
            engine.clreplacedes().remove(name);
        } else if (name.lastIndexOf(TemplateClreplaced.CN_SUFFIX) == -1) {
            return null;
        } else {
            int pos = name.indexOf("$");
            if (-1 != pos) {
                // should be an inner clreplaced, let's try to create it load it from cache
                // 1. find the root clreplaced
                String parentCN = name.substring(0, pos);
                TemplateClreplaced parent = engine.clreplacedes().getByClreplacedName(parentCN);
                if (null == parent) {
                    throw new RuntimeException("Cannot find inner clreplaced def: " + name);
                }
                TemplateClreplaced tc = TemplateClreplaced.createInnerClreplaced(name, null, parent);
                engine.clreplacedCache().loadTemplateClreplaced(tc);
                byte[] bc = tc.enhancedByteCode;
                if (null == bc) {
                    // inner clreplaced byte code cache missed some how, let's try to recover it
                    while ((null != parent) && parent.isInner()) {
                        parent = parent.root();
                    }
                    if (null == parent) {
                        throw new RuntimeException("Unexpected: cannot find the root clreplaced of inner clreplaced: " + name);
                    }
                    parent.reset();
                    parent.refresh(true);
                    parent.compile();
                    // now try again and see if we can find the clreplaced definition
                    tc = engine.clreplacedes().getByClreplacedName(name);
                    Clreplaced<?> c = tc.javaClreplaced;
                    if (null != c)
                        return c;
                    bc = tc.enhancedByteCode;
                    if (null == bc) {
                        throw new RuntimeException("Cannot find bytecode cache for inner clreplaced: " + name);
                    }
                }
                tc.javaClreplaced = (Clreplaced<ITemplate>) defineClreplaced(tc.name(), bc, 0, bc.length, protectionDomain);
                return tc.javaClreplaced;
            }
        }
        return null;
    }

    private String getPackageName(String name) {
        int dot = name.lastIndexOf('.');
        return dot > -1 ? name.substring(0, dot) : "";
    }

    private void loadPackage(String clreplacedName) {
        // find the package clreplaced name
        int symbol = clreplacedName.indexOf("$");
        if (symbol > -1) {
            clreplacedName = clreplacedName.substring(0, symbol);
        }
        symbol = clreplacedName.lastIndexOf(".");
        if (symbol > -1) {
            clreplacedName = clreplacedName.substring(0, symbol) + ".package-info";
        } else {
            clreplacedName = "package-info";
        }
        if (findLoadedClreplaced(clreplacedName) == null) {
            loadTemplateClreplaced(clreplacedName);
        }
    }

    private Set<String> notFoundTypes = null;

    private boolean typeNotFound(String name) {
        if (null == notFoundTypes) {
            notFoundTypes = engine.clreplacedes().compiler.notFoundTypes;
        }
        return notFoundTypes.contains(name);
    }

    private void setTypeNotFound(String name) {
        if (null == notFoundTypes) {
            notFoundTypes = engine.clreplacedes().compiler.notFoundTypes;
        }
        if (engine.isProdMode()) {
            notFoundTypes.add(name);
        } else if (name.matches("^(java\\.|play\\.|com\\.greenlaw110\\.).*")) {
            notFoundTypes.add(name);
        }
    }

    /**
     * Search for the byte code of the given clreplaced.
     */
    protected byte[] getClreplacedDefinition(final String name0) {
        if (typeNotFound(name0))
            return null;
        byte[] ba = null;
        String name = name0.replace(".", "/") + ".clreplaced";
        InputStream is = getResourcereplacedtream(name);
        if (null != is) {
            try {
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                byte[] buffer = new byte[8192];
                int count;
                while ((count = is.read(buffer, 0, buffer.length)) > 0) {
                    os.write(buffer, 0, count);
                }
                ba = os.toByteArray();
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        if (null == ba) {
            IByteCodeHelper helper = engine.conf().byteCodeHelper();
            if (null != helper) {
                ba = helper.findByteCode(name0);
            }
        }
        if (null == ba) {
            setTypeNotFound(name0);
        }
        return ba;
    }

    public void detectChange(TemplateClreplaced tc) {
        if (engine.isProdMode() && null != tc.name())
            return;
        if (!tc.refresh())
            return;
        if (tc.compile() == null) {
            engine.clreplacedes().remove(tc);
            currentState = new TemplateClreplacedloaderState();
        } else {
            throw new ClreplacedReloadException("Need reload");
        }
    }

    /**
     * Detect Template changes
     */
    public void detectChanges() {
        if (engine.isProdMode())
            return;
        // Now check for file modification
        List<TemplateClreplaced> modifieds = new ArrayList<TemplateClreplaced>();
        for (TemplateClreplaced tc : engine.clreplacedes().all()) {
            if (tc.refresh())
                modifieds.add(tc);
        }
        Set<TemplateClreplaced> modifiedWithDependencies = new HashSet<TemplateClreplaced>();
        modifiedWithDependencies.addAll(modifieds);
        List<ClreplacedDefinition> newDefinitions = new ArrayList<ClreplacedDefinition>();
        boolean dirtySig = false;
        for (TemplateClreplaced tc : modifiedWithDependencies) {
            if (tc.compile() == null) {
                engine.clreplacedes().remove(tc);
                // show others that we have changed..
                currentState = new TemplateClreplacedloaderState();
            } else {
                int sigChecksum = tc.sigChecksum;
                tc.enhance();
                if (sigChecksum != tc.sigChecksum) {
                    dirtySig = true;
                }
                newDefinitions.add(new ClreplacedDefinition(tc.javaClreplaced, tc.enhancedByteCode));
                // show others that we have changed..
                currentState = new TemplateClreplacedloaderState();
            }
        }
        if (!newDefinitions.isEmpty()) {
            throw new ClreplacedReloadException("Need Reload");
        }
        // Check signature (variable name & annotations aware !)
        if (dirtySig) {
            throw new ClreplacedReloadException("Signature change !");
        }
        // Now check if there is new clreplacedCache or removed clreplacedCache
        int hash = computePathHash();
        if (hash != this.pathHash) {
            // Remove clreplaced for deleted files !!
            for (TemplateClreplaced tc : engine.clreplacedes().all()) {
                if (!tc.templateResource.isValid()) {
                    engine.clreplacedes().remove(tc);
                    // show others that we have changed..
                    currentState = new TemplateClreplacedloaderState();
                }
            }
            throw new ClreplacedReloadException("Path has changed");
        }
    }

    /**
     * Used to track change of the application sources path
     */
    int pathHash = 0;

    public int computePathHash() {
        return engine.isProdMode() ? 0 : clreplacedStateHashCreator.computePathHash(engine.conf().tmpDir());
    }
}

18 View Complete Implementation : TemplateClassManager.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Created by IntelliJ IDEA.
 * User: luog
 * Date: 18/01/12
 * Time: 8:58 PM
 * To change this template use File | Settings | File Templates.
 */
public clreplaced TemplateClreplacedManager {

    protected final static ILogger logger = Logger.get(TemplateClreplacedManager.clreplaced);

    // private static final ILogger logger = Logger.get(TemplateClreplacedCache.clreplaced);
    public RythmEngine engine = null;

    /**
     * Reference to the eclipse compiler.
     */
    TemplateCompiler compiler = null;

    /**
     * Index template clreplaced with clreplaced name
     */
    public Map<String, TemplateClreplaced> clsNameIdx = new HashMap<String, TemplateClreplaced>();

    /**
     * Index template clreplaced with inline template content or template file name
     */
    public Map<Object, TemplateClreplaced> tmplIdx = new HashMap<Object, TemplateClreplaced>();

    public TemplateClreplacedManager(RythmEngine engine) {
        if (null == engine)
            throw new NullPointerException();
        this.engine = engine;
        this.compiler = new TemplateCompiler(this);
    }

    /**
     * Clear the clreplacedCache cache
     */
    public void clear() {
        clsNameIdx = new HashMap<String, TemplateClreplaced>();
        tmplIdx = new HashMap<Object, TemplateClreplaced>();
    }

    /**
     * All loaded clreplacedes.
     *
     * @return All loaded clreplacedes
     */
    public List<TemplateClreplaced> all() {
        return new ArrayList<TemplateClreplaced>(clsNameIdx.values());
    }

    /**
     * Get a clreplaced by name
     *
     * @param name The fully qualified clreplaced name
     * @return The TemplateClreplaced or null
     */
    public TemplateClreplaced getByClreplacedName(String name) {
        TemplateClreplaced tc = clsNameIdx.get(name);
        checkUpdate(tc);
        return tc;
    }

    public TemplateClreplaced getByTemplate(Object name, boolean checkResource) {
        TemplateClreplaced tc = tmplIdx.get(name);
        if (checkResource && null == tc) {
            // try to see if resourceLoader has some kind of name transform
            ITemplateResource r = engine.resourceManager().getResource(name.toString());
            if (!r.isValid()) {
                return null;
            }
            tc = tmplIdx.get(r.getKey());
        }
        checkUpdate(tc);
        return tc;
    }

    public TemplateClreplaced getByTemplate(Object name) {
        return getByTemplate(name, true);
    }

    private void checkUpdate(TemplateClreplaced tc) {
        if (null == tc || engine.isProdMode()) {
            return;
        }
        if (logger.isTraceEnabled()) {
            logger.trace("checkUpdate for template: %s", tc.getKey());
        }
        try {
            engine.clreplacedLoader().detectChange(tc);
        } catch (ClreplacedReloadException e) {
            engine.restart(e);
        }
    }

    List<TemplateClreplaced> getEmbeddedClreplacedes(String name) {
        List<TemplateClreplaced> l = new ArrayList<TemplateClreplaced>();
        for (Map.Entry<String, TemplateClreplaced> entry : clsNameIdx.entrySet()) {
            if (entry.getKey().startsWith(name + "$")) {
                l.add(entry.getValue());
            }
        }
        return l;
    }

    @Deprecated
    public void add(Object key, TemplateClreplaced templateClreplaced) {
    // tmplIdx.put(key, templateClreplaced);
    }

    public void add(TemplateClreplaced templateClreplaced) {
        // clsNameIdx.put(templateClreplaced.name0(), templateClreplaced);
        clsNameIdx.put(templateClreplaced.name(), templateClreplaced);
        if (!templateClreplaced.isInner()) {
            ITemplateResource rsrc = templateClreplaced.templateResource;
            Object key = rsrc.getKey();
            tmplIdx.put(key, templateClreplaced);
            if (rsrc instanceof ClreplacedpathTemplateResource) {
                String key2 = ((ClreplacedpathTemplateResource) rsrc).getKey2();
                if (key != key2) {
                    tmplIdx.put(key2, templateClreplaced);
                }
            }
        }
    }

    public void remove(TemplateClreplaced templateClreplaced) {
        if (null == templateClreplaced)
            return;
        if (templateClreplaced.isInner()) {
            clsNameIdx.remove(templateClreplaced.name());
            return;
        }
        // remove versioned link
        clsNameIdx.remove(templateClreplaced.name());
        // remove unversioned link
        String name0 = templateClreplaced.name0();
        clsNameIdx.remove(name0);
        List<String> embedded = new ArrayList<String>();
        for (String cn : clsNameIdx.keySet()) {
            if (cn.matches(name0 + "v[0-9]+\\$.*"))
                embedded.add(cn);
        }
        for (String cn : embedded) clsNameIdx.remove(cn);
        if (null != templateClreplaced && null != templateClreplaced.templateResource)
            tmplIdx.remove(templateClreplaced.getKey());
    }

    public void remove(String name) {
        TemplateClreplaced templateClreplaced = clsNameIdx.get(name);
        remove(templateClreplaced);
    }

    public boolean hasClreplaced(String name) {
        return clsNameIdx.containsKey(name);
    }

    @Override
    public String toString() {
        return clsNameIdx.toString();
    }
}

18 View Complete Implementation : AutoToString.java
Copyright Apache License 2.0
Author : rythmengine
@Override
public CodeBuilder createCodeBuilder(String template, String clreplacedName, String tagName, TemplateClreplaced templateClreplaced, RythmEngine engine) {
    return new AutoToStringCodeBuilder(template, clreplacedName, tagName, templateClreplaced, engine, this);
}

18 View Complete Implementation : ParserBase.java
Copyright Apache License 2.0
Author : rythmengine
public abstract clreplaced ParserBase implements IParser {

    public static final ParserBase NULL_INST = new ParserBase() {

        @Override
        public Token go() {
            return null;
        }
    };

    protected final static ILogger logger = Logger.get(IParser.clreplaced);

    public static Pattern pattern(String regex, Object... args) {
        if (0 < args.length)
            regex = String.format(regex, args);
        return Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    }

    private final IDialect d_;

    private final IContext c_;

    protected final RythmEngine engine_;

    private ParserBase() {
        d_ = null;
        c_ = null;
        engine_ = null;
    }

    protected ParserBase(IContext context) {
        if (null == context)
            throw new NullPointerException();
        d_ = context.getDialect();
        c_ = context;
        engine_ = context.getEngine();
    }

    protected final IDialect dialect() {
        return d_;
    }

    protected final String a() {
        return d_.a();
    }

    protected final String remain() {
        return c_.getRemain();
    }

    protected final int currentLine() {
        return c_.currentLine();
    }

    protected final char peek() {
        return c_.peek();
    }

    protected final char pop() {
        return c_.pop();
    }

    public final IContext ctx() {
        return c_;
    }

    protected final CodeBuilder builder() {
        return c_.getCodeBuilder();
    }

    protected final void step(int i) {
        c_.step(i);
    }

    protected final void raiseParseException(String msg, Object... args) {
        CaretParserFactoryBase.raiseParseException(ctx(), msg, args);
    }

    protected final void checkRestrictedClreplaced(String code) {
        if (Rythm.insideSandbox()) {
            String s = Sandbox.hasAccessToRestrictedClreplacedes(ctx().getEngine(), code);
            if (S.notEmpty(s)) {
                raiseParseException("Access to restricted clreplaced [%s] is blocked in sandbox mode", s);
            }
        }
    }

    protected boolean isLastBuilderLiteral() {
        IContext ctx = ctx();
        if (ctx.cursor() == 0)
            return false;
        CodeBuilder cb = ctx.getCodeBuilder();
        return cb.isLastBuilderLiteral();
    }

    protected void processFollowingOpenBraceAndLineBreak(boolean leadingLB) {
        IContext ctx = ctx();
        int cnt = 0;
        int lbCnt = 0;
        StringBuilder sb = new StringBuilder();
        boolean braceOpen = false;
        while (ctx.hasRemain()) {
            char c0 = ctx.pop();
            cnt--;
            if (c0 == ' ' || c0 == '\t') {
                if (braceOpen)
                    sb.append(c0);
                continue;
            } else if (c0 == '\n') {
                if (braceOpen) {
                    if (!leadingLB)
                        sb.append("\n");
                    ctx.getCodeBuilder().addBuilder(new Token.StringToken(sb.toString(), ctx));
                    break;
                } else {
                    lbCnt++;
                    continue;
                }
            } else if (c0 == '{') {
                if (!braceOpen) {
                    braceOpen = true;
                    cnt = 0;
                    continue;
                } else {
                    ctx.step(cnt);
                    break;
                }
            } else {
                ctx.step(cnt);
                break;
            }
        }
    }

    // -- for testing purpose
    public static void p(int i, Regex r) {
        if (0 == i) {
            System.out.println(i + ": " + r.stringMatched());
        } else {
            System.out.println(i + ": " + r.stringMatched(i));
        }
    }

    public static void p(String s, Regex r) {
        if (r.search(s))
            p(r);
    }

    public static void p(String s, Regex r, int max) {
        if (r.search(s))
            p(r, max);
    }

    public static void p(Regex r, int max) {
        for (int i = 0; i < max; ++i) {
            p(i, r);
        }
    }

    public static void p(Regex r) {
        p(r, 6);
    }
}

17 View Complete Implementation : RythmTemplate.java
Copyright Apache License 2.0
Author : actframework
public static RythmTemplate find(RythmEngine engine, String path) {
    ITemplateResource resource = engine.resourceManager().getResource(path);
    if (!resource.isValid()) {
        return null;
    } else {
        return new RythmTemplate(engine, path);
    }
}

17 View Complete Implementation : EventBus.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Dispatch {@link IEvent events}
 */
public clreplaced EventBus implements IEventDispatcher {

    protected static final ILogger logger = Logger.get(EventBus.clreplaced);

    private final RythmEngine engine;

    private final ISourceCodeEnhancer sourceCodeEnhancer;

    // private final IByteCodeEnhancer byteCodeEnhancer;
    private final IRenderExceptionHandler exceptionHandler;

    private static clreplaced RythmListenerDispatcher implements IRythmListener {

        private List<IRythmListener> listeners = new ArrayList<IRythmListener>();

        @Override
        public void onRender(ITemplate template) {
            for (IRythmListener l : listeners) {
                try {
                    l.onRender(template);
                } catch (RuntimeException e) {
                    logger.warn(e, "Error executing onRender method on rythm listener: " + l.getClreplaced());
                }
            }
        }

        @Override
        public void rendered(ITemplate template) {
            for (IRythmListener l : listeners) {
                try {
                    l.rendered(template);
                } catch (RuntimeException e) {
                    logger.warn(e, "Error executing rendered method on rythm listener: " + l.getClreplaced());
                }
            }
        }

        @Override
        public void enterInvokeTemplate(TemplateBase caller) {
            for (IRythmListener l : listeners) {
                try {
                    l.enterInvokeTemplate(caller);
                } catch (RuntimeException e) {
                    logger.warn(e, "Error executing enterInvokeTemplate method on rythm listener: " + l.getClreplaced());
                }
            }
        }

        @Override
        public void exitInvokeTemplate(TemplateBase caller) {
            for (IRythmListener l : listeners) {
                try {
                    l.exitInvokeTemplate(caller);
                } catch (RuntimeException e) {
                    logger.warn(e, "Error executing exitInvokeTemplate method on rythm listener: " + l.getClreplaced());
                }
            }
        }

        @Override
        public void onInvoke(ITag tag) {
            for (IRythmListener l : listeners) {
                try {
                    l.onInvoke(tag);
                } catch (RuntimeException e) {
                    logger.warn(e, "Error executing onInvoke method on rythm listener: " + l.getClreplaced());
                }
            }
        }

        @Override
        public void invoked(ITag tag) {
            for (IRythmListener l : listeners) {
                try {
                    l.invoked(tag);
                } catch (RuntimeException e) {
                    logger.warn(e, "Error executing invoked method on rythm listener: " + l.getClreplaced());
                }
            }
        }
    }

    private final RythmListenerDispatcher renderListener = new RythmListenerDispatcher();

    public final void registerRenderListener(IRythmListener l) {
        renderListener.listeners.add(l);
    }

    public final void unregisterRenderListener(IRythmListener l) {
        renderListener.listeners.remove(l);
    }

    public EventBus(RythmEngine engine) {
        this.engine = engine;
        RythmConfiguration conf = engine.conf();
        sourceCodeEnhancer = conf.get(RythmConfigurationKey.CODEGEN_SOURCE_CODE_ENHANCER);
        // byteCodeEnhancer = conf.get(RythmConfigurationKey.CODEGEN_BYTE_CODE_ENHANCER);
        exceptionHandler = conf.get(RythmConfigurationKey.RENDER_EXCEPTION_HANDLER);
        IRythmListener l = conf.get(RythmConfigurationKey.RENDER_LISTENER);
        if (null != l) {
            registerRenderListener(l);
        }
        registerHandlers();
    }

    private static interface IEventHandler<RETURN, PARAM> {

        RETURN handleEvent(RythmEngine engine, PARAM param);
    }

    private Map<IEvent<?, ?>, IEventHandler<?, ?>> dispatcher = new HashMap<IEvent<?, ?>, IEventHandler<?, ?>>();

    @Override
    public Object accept(IEvent event, Object param) {
        IEventHandler handler = dispatcher.get(event);
        if (null != handler) {
            return handler.handleEvent(engine, param);
        }
        return null;
    }

    private void registerHandlers() {
        Map<IEvent<?, ?>, IEventHandler<?, ?>> m = dispatcher;
        m.put(RythmEvents.ON_PARSE, new IEventHandler<String, CodeBuilder>() {

            @Override
            public String handleEvent(RythmEngine engine, CodeBuilder c) {
                // pre process template source
                String tmpl = c.template();
                if (tmpl == null) {
                    String msg = "template for " + c.tagName + " not available";
                    throw new RuntimeException(msg);
                }
                tmpl = tmpl.replaceAll("(\\r\\n)", "\n");
                tmpl = tmpl.replaceAll("\\r", "\n");
                return tmpl;
            }
        });
        m.put(RythmEvents.PARSE_FAILED, new IEventHandler<Void, TemplateClreplaced>() {

            @Override
            public Void handleEvent(RythmEngine engine, TemplateClreplaced tc) {
                TemplateResourceManager.rollbackTmpBlackList();
                return null;
            }
        });
        m.put(RythmEvents.ON_BUILD_JAVA_SOURCE, new IEventHandler<Void, CodeBuilder>() {

            @Override
            public Void handleEvent(RythmEngine engine, CodeBuilder cb) {
                ISourceCodeEnhancer ce = sourceCodeEnhancer;
                if (null == ce)
                    return null;
                if (cb.basicTemplate()) {
                    // basic template do not have common codes
                    return null;
                }
                // add common render args
                Map<String, ?> defArgs = ce.getRenderArgDescriptions();
                for (Map.Entry<String, ?> entry : defArgs.entrySet()) {
                    Object o = entry.getValue();
                    String type = (o instanceof Clreplaced<?>) ? ((Clreplaced<?>) o).getName() : o.toString();
                    cb.addRenderArgs(-1, type, entry.getKey());
                }
                // add common imports
                for (String s : ce.imports()) {
                    cb.addImport(s, -1);
                }
                return null;
            }
        });
        m.put(RythmEvents.COMPILED, new IEventHandler<byte[], byte[]>() {

            @Override
            public byte[] handleEvent(RythmEngine engine, byte[] bytes) {
                TemplateResourceManager.commitTmpBlackList();
                return bytes;
            }
        });
        m.put(RythmEvents.COMPILE_FAILED, new IEventHandler<Void, TemplateClreplaced>() {

            @Override
            public Void handleEvent(RythmEngine engine, TemplateClreplaced tc) {
                TemplateResourceManager.rollbackTmpBlackList();
                return null;
            }
        });
        m.put(RythmEvents.ON_CLOSING_JAVA_CLreplaced, new IEventHandler<Void, CodeBuilder>() {

            @Override
            public Void handleEvent(RythmEngine engine, CodeBuilder cb) {
                // add common source code
                ISourceCodeEnhancer ce = sourceCodeEnhancer;
                if (null == ce) {
                    return null;
                }
                if (cb.basicTemplate()) {
                    // basic template do not have common codes
                    return null;
                }
                cb.np(ce.sourceCode());
                cb.pn();
                return null;
            }
        });
        m.put(RythmEvents.ON_RENDER, new IEventHandler<Void, ITemplate>() {

            @Override
            public Void handleEvent(RythmEngine engine, ITemplate template) {
                ISourceCodeEnhancer ce = engine.conf().sourceEnhancer();
                if (null != ce) {
                    ce.setRenderArgs(template);
                }
                renderListener.onRender(template);
                return null;
            }
        });
        m.put(RythmEvents.RENDERED, new IEventHandler<Void, ITemplate>() {

            @Override
            public Void handleEvent(RythmEngine engine, ITemplate template) {
                engine.renderSettings.clear();
                Rythm.RenderTime.clear();
                renderListener.rendered(template);
                return null;
            }
        });
        m.put(RythmEvents.ON_TAG_INVOCATION, new IEventHandler<Void, F.T2<ITemplate, ITag>>() {

            @Override
            public Void handleEvent(RythmEngine engine, F.T2<ITemplate, ITag> param) {
                renderListener.onInvoke(param._2);
                return null;
            }
        });
        m.put(RythmEvents.TAG_INVOKED, new IEventHandler<Void, F.T2<TemplateBase, ITag>>() {

            @Override
            public Void handleEvent(RythmEngine engine, F.T2<TemplateBase, ITag> param) {
                renderListener.invoked(param._2);
                return null;
            }
        });
        m.put(RythmEvents.ENTER_INVOKE_TEMPLATE, new IEventHandler<Void, TemplateBase>() {

            @Override
            public Void handleEvent(RythmEngine engine, TemplateBase caller) {
                renderListener.enterInvokeTemplate(caller);
                return null;
            }
        });
        m.put(RythmEvents.EXIT_INVOKE_TEMPLATE, new IEventHandler<Void, TemplateBase>() {

            @Override
            public Void handleEvent(RythmEngine engine, TemplateBase caller) {
                renderListener.exitInvokeTemplate(caller);
                return null;
            }
        });
        m.put(RythmEvents.ON_RENDER_EXCEPTION, new IEventHandler<Boolean, F.T2<TemplateBase, Exception>>() {

            @Override
            public Boolean handleEvent(RythmEngine engine, F.T2<TemplateBase, Exception> param) {
                if (null == exceptionHandler)
                    return false;
                return exceptionHandler.handleTemplateExecutionException(param._2, param._1);
            }
        });
    }
}

17 View Complete Implementation : RythmSecurityManager.java
Copyright Apache License 2.0
Author : rythmengine
@Override
public void checkPropertyAccess(String key) {
    if (key.startsWith("rythm.")) {
        key = key.substring(7);
    }
    if (null != RythmConfigurationKey.valueOfIgnoreCase(key)) {
        return;
    }
    RythmEngine e = engine();
    if (null == e) {
        // not in Rendering process yet, let's replacedume it's safe to check system properties
        return;
    }
    String s = e.conf().allowedSystemProperties();
    if (s.indexOf(key) > -1)
        return;
    if (e.isDevMode()) {
        logger.info("checking security on property[%s] access on [%s]", key, s);
    }
    checkRythm();
    if (null != csm)
        csm.checkPropertyAccess(key);
    if (null != osm)
        osm.checkPropertyAccess(key);
}

17 View Complete Implementation : GithubIssue325Test.java
Copyright Apache License 2.0
Author : rythmengine
@Test
public void testNonExistingTemplate() throws Exception {
    File templateDir = GithubIssue321Test.getTemplateDir();
    File template = new File(templateDir, "testNonExistingXYZ.rythm");
    replacedertFalse(template.exists());
    Map<String, Object> conf = new HashMap<String, Object>();
    conf.put(RythmConfigurationKey.HOME_TEMPLATE.getKey(), templateDir.getAbsolutePath());
    RythmEngine engine = new RythmEngine(conf);
    Map<String, Object> rootMap = new HashMap<String, Object>();
    try {
        String result = engine.render(template, rootMap);
        fail("There should be an exception");
        // just to avoid warning for result not being replacedigned to
        replacedertNull(result);
    } catch (Throwable th) {
        // debug=true;
        if (debug) {
            th.printStackTrace();
            System.out.println(th.getMessage());
        }
        replacedertFalse(th.getMessage().contains("Null"));
        replacedertTrue(th.getMessage().contains("exist"));
    }
}

16 View Complete Implementation : FastTagBridge.java
Copyright Apache License 2.0
Author : rythmengine
private static void registerFastTag(RythmEngine engine, Method m, String ns, Clreplaced<?> jc) {
    int flag = m.getModifiers();
    if (!Modifier.isPublic(flag) || !Void.TYPE.equals(m.getReturnType()))
        return;
    if (m.getParameterTypes().length != 5)
        return;
    // note, need to strip off leading '_' from method name
    FastTagBridge tag = new FastTagBridge(ns, m.getName().substring(1), jc);
    ITemplate tmpl = engine.getRegisteredTemplate(tag.__getName());
    // FastTagBridge has lowest priority, thus if there are other tags already registered
    // with the same name, FastTag bridge will not be registered again
    if (null == tmpl || (tmpl instanceof FastTagBridge))
        engine.registerTemplate(tag);
}

16 View Complete Implementation : JavaExtensionBridge.java
Copyright Apache License 2.0
Author : rythmengine
public static void registerPlayBuiltInJavaExtensions(RythmEngine engine) {
    long l = System.currentTimeMillis();
    String[] voidExtensions = { "enumValues", "asXml", "eval", "since", "addSlashes", "pluralize", "page", "slugify", "last" };
    String[] nonVoidExtensions = { "contains", "add", "remove", "pad", "page", "since", "asdate", "cut", "divisibleBy", "pluralize", "slugify", "yesno", "join" };
    ExtensionManager em = engine.extensionManager();
    for (String s : voidExtensions) {
        em.registerJavaExtension(new PlayVoidParameterExtension(s));
    }
    for (String s : nonVoidExtensions) {
        em.registerJavaExtension(new PlayParameterExtension(s, ".+"));
    }
    // moved to codegen.source_code_enhancer.impl: engine.registerGlobalImports("play.templates.JavaExtensions");
    RythmPlugin.debug("%sms to register play built-in java extension", System.currentTimeMillis() - l);
}

16 View Complete Implementation : RythmPlugin.java
Copyright Apache License 2.0
Author : rythmengine
private void registerJavaTag(Clreplaced<?> jc, RythmEngine engine) {
    int flag = jc.getModifiers();
    if (Modifier.isAbstract(flag))
        return;
    try {
        Constructor<?> c = jc.getConstructor(new Clreplaced[] {});
        c.setAccessible(true);
        FastRythmTag tag = (FastRythmTag) c.newInstance();
        engine.registerTemplate(tag);
    } catch (Exception e) {
        throw new UnexpectedException("Error initialize JavaTag: " + jc.getName(), e);
    }
}

16 View Complete Implementation : TemplateClass.java
Copyright Apache License 2.0
Author : rythmengine
/**
 * Define the data structure hold template clreplaced/template src/generated java src
 */
public clreplaced TemplateClreplaced {

    private static final ILogger logger = Logger.get(TemplateClreplaced.clreplaced);

    public static final String CN_SUFFIX = "__R_T_C__";

    private static final String NO_INCLUDE_CLreplaced = "NO_INCLUDE_CLreplaced";

    private static final ITemplate NULL_TEMPLATE = new TagBase() {

        @Override
        public ITemplate __cloneMe(RythmEngine engine, ITemplate caller) {
            return null;
        }
    };

    /**
     * Store root level template clreplaced, e.g. the one that is not an embedded clreplaced
     */
    private TemplateClreplaced root;

    private boolean inner = false;

    private RythmEngine engine = null;

    private boolean enhancing = false;

    private transient List<TemplateClreplaced> embeddedClreplacedes = new ArrayList<TemplateClreplaced>();

    /**
     * The fully qualified clreplaced name
     */
    private String name;

    public TemplateClreplaced extendedTemplateClreplaced;

    private Set<TemplateClreplaced> includedTemplateClreplacedes = new HashSet<TemplateClreplaced>();

    private String includeTemplateClreplacedNames = null;

    private Map<String, String> includeTagTypes = new HashMap<String, String>();

    private String tagName;

    /**
     * The Java source
     */
    public String javaSource;

    /**
     * The compiled byteCode
     */
    public byte[] javaByteCode;

    /**
     * The enhanced byteCode
     */
    public byte[] enhancedByteCode;

    /**
     * Store a list of import path, i.e. those imports ends with ".*"
     */
    public Set<String> importPaths;

    /**
     * The in JVM loaded clreplaced
     */
    public Clreplaced<ITemplate> javaClreplaced;

    /**
     * The in JVM loaded package
     */
    public Package javaPackage;

    /**
     * The code type could be HTML, JS, JSON etc
     */
    public ICodeType codeType;

    /**
     * Is this clreplaced compiled
     */
    private boolean compiled;

    /**
     * Signatures checksum
     */
    public int sigChecksum;

    /**
     * Mark if this is a valid Rythm Template
     */
    private boolean isValid = true;

    /**
     * CodeBuilder to generate java source code
     * <p/>
     * Could be used to merge state into including template clreplaced codeBuilder
     */
    public CodeBuilder codeBuilder;

    /**
     * The ITemplate instance
     */
    private TemplateBase templateInstance;

    /**
     * Store the resource loader clreplaced name
     */
    private String resourceLoaderClreplaced;

    /**
     * the template resource
     */
    public ITemplateResource templateResource;

    /**
     * specify the dialect for the template
     */
    transient private IDialect dialect;

    private String magic = S.random(4);

    public TemplateClreplaced root() {
        return root;
    }

    private TemplateClreplaced() {
    }

    public boolean isInner() {
        return inner;
    }

    private RythmEngine engine() {
        return null == engine ? Rythm.engine() : engine;
    }

    public String name0() {
        return name();
    }

    public String name() {
        return name;
    }

    /*
     * WRITE : includedTemplateClreplacedes, includeTagTypes
     */
    public void addIncludeTemplateClreplaced(TemplateClreplaced tc) {
        includedTemplateClreplacedes.add(tc);
        includeTagTypes.putAll(tc.includeTagTypes);
    }

    /*
     * WRITE : includeTemplateClreplacedNames
     */
    public String refreshIncludeTemplateClreplacedNames() {
        if (includedTemplateClreplacedes.isEmpty()) {
            includeTemplateClreplacedNames = NO_INCLUDE_CLreplaced;
            return NO_INCLUDE_CLreplaced;
        }
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (TemplateClreplaced tc : includedTemplateClreplacedes) {
            if (!first) {
                sb.append(",");
            } else {
                first = false;
            }
            sb.append(tc.tagName);
        }
        includeTemplateClreplacedNames = sb.toString();
        return sb.toString();
    }

    /*
     *  WRITE : includeTagTypes
     */
    public void setTagType(String tagName, String type) {
        includeTagTypes.put(tagName, type);
    }

    public boolean returnObject(String tagName) {
        String retType = includeTagTypes.get(tagName);
        if (null != retType) {
            return !"void".equals(retType);
        }
        if (null != extendedTemplateClreplaced) {
            return extendedTemplateClreplaced.returnObject(tagName);
        }
        return true;
    }

    public String serializeIncludeTagTypes() {
        if (includeTagTypes.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        boolean empty = true;
        for (Map.Entry<String, String> entry : includeTagTypes.entrySet()) {
            if (!empty) {
                sb.append(";");
            } else {
                empty = false;
            }
            sb.append(entry.getKey()).append(":").append(entry.getValue());
        }
        return sb.toString();
    }

    /*
     * WRITE : includeTagTypes
     */
    public void deserializeIncludeTagTypes(String s) {
        includeTagTypes = new HashMap<String, String>();
        if (S.isEmpty(s)) {
            return;
        }
        String[] sa = s.split(";");
        for (String s0 : sa) {
            String[] sa0 = s0.split(":");
            if (sa0.length != 2) {
                throw new IllegalArgumentException("Unknown include tag types string: " + s);
            }
            includeTagTypes.put(sa0[0], sa0[1]);
        }
    }

    /**
     * If not null then this template is a tag
     */
    public String getTagName() {
        return tagName;
    }

    /**
     * The template source
     */
    public String getTemplateSource() {
        return getTemplateSource(false);
    }

    public String getTemplateSource(boolean includeRoot) {
        if (null != templateResource) {
            return templateResource.asTemplateContent();
        }
        if (!includeRoot) {
            return "";
        }
        TemplateClreplaced parent = root;
        while ((null != parent) && parent.isInner()) {
            parent = parent.root;
        }
        return null == parent ? "" : parent.getTemplateSource();
    }

    /**
     * Is this template resource coming from a literal String or from a loaded resource like file
     */
    public boolean isStringTemplate() {
        return templateResource instanceof StringTemplateResource;
    }

    public String getResourceLoaderClreplaced() {
        return resourceLoaderClreplaced;
    }

    private TemplateClreplaced(RythmEngine engine) {
        this.engine = null == engine ? null : engine.isSingleton() ? null : engine;
    }

    /**
     * Construct a TemplateClreplaced instance using template source file
     *
     * @param file the template source file
     */
    public TemplateClreplaced(File file, RythmEngine engine) {
        this(engine.resourceManager().get(file), engine);
    }

    /**
     * Construct a TemplateClreplaced instance using template source content or file path
     *
     * @param template
     */
    public TemplateClreplaced(String template, RythmEngine engine) {
        this(engine.resourceManager().get(template), engine);
    }

    /**
     * Construct a TemplateClreplaced instance using template source content or file path
     *
     * @param template
     */
    public TemplateClreplaced(String template, RythmEngine engine, IDialect dialect) {
        this(engine.resourceManager().get(template), engine, dialect);
    }

    public TemplateClreplaced(ITemplateResource resource, RythmEngine engine) {
        this(resource, engine, false);
    }

    public TemplateClreplaced(ITemplateResource resource, RythmEngine engine, IDialect dialect) {
        this(resource, engine, false, dialect);
    }

    /*
     * WRITE : templateResource
     */
    public TemplateClreplaced(ITemplateResource resource, RythmEngine engine, boolean noRefresh) {
        this(engine);
        if (null == resource) {
            throw new NullPointerException();
        }
        // resource.setEngine(engine());
        templateResource = resource;
        if (!noRefresh) {
            refresh(false);
        }
    }

    /*
     * WRITE : templateResource
     */
    public TemplateClreplaced(ITemplateResource resource, RythmEngine engine, boolean noRefresh, IDialect dialect) {
        this(engine);
        if (null == resource) {
            throw new NullPointerException();
        }
        // resource.setEngine(engine());
        templateResource = resource;
        this.dialect = dialect;
        if (!noRefresh) {
            refresh(false);
        }
    }

    /**
     * Return the name or key of the template resource
     *
     * @return the key
     */
    public String getKey() {
        return null == templateResource ? name : templateResource.getKey().toString();
    }

    @SuppressWarnings("unchecked")
    private Clreplaced<?> loadJavaClreplaced() throws Exception {
        if (null == javaSource) {
            if (null == javaSource) {
                refresh(false);
            }
        }
        RythmEngine engine = engine();
        TemplateClreplacedLoader cl = engine.clreplacedLoader();
        if (null == cl) {
            throw new NullPointerException();
        }
        Clreplaced<?> c = cl.loadClreplaced(name, true);
        if (null == javaClreplaced) {
            javaClreplaced = (Clreplaced<ITemplate>) c;
        }
        return c;
    }

    private ITemplate templateInstance_(RythmEngine engine) {
        if (!isValid) {
            return NULL_TEMPLATE;
        }
        if (null == templateInstance) {
            try {
                Clreplaced<?> clz = loadJavaClreplaced();
                TemplateBase tmpl = (TemplateBase) clz.newInstance();
                tmpl.__setTemplateClreplaced(this);
                engine.registerTemplate(tmpl);
                // engine.registerTemplate(getFullName(true), tmpl);
                templateInstance = tmpl;
            } catch (RythmException e) {
                throw e;
            } catch (Exception e) {
                throw new RuntimeException("Error load template instance for " + getKey(), e);
            }
        }
        if (!engine.isProdMode()) {
            engine.registerTemplate(templateInstance);
            // check parent clreplaced change
            Clreplaced<?> c = templateInstance.getClreplaced();
            Clreplaced<?> pc = c.getSuperclreplaced();
            if (null != pc && !Modifier.isAbstract(pc.getModifiers())) {
                engine.clreplacedes().getByClreplacedName(pc.getName());
            }
        }
        return templateInstance;
    }

    public ITemplate asTemplate(ICodeType type, Locale locale, RythmEngine engine) {
        if (null == name || engine.isDevMode()) {
            refresh(false);
        }
        TemplateBase tmpl = (TemplateBase) templateInstance_(engine).__cloneMe(engine(), null);
        if (tmpl != null) {
            tmpl.__prepareRender(type, locale, engine);
        }
        return tmpl;
    }

    public ITemplate asTemplate(RythmEngine engine) {
        return asTemplate(null, null, engine);
    }

    public ITemplate asTemplate(ITemplate caller, RythmEngine engine) {
        TemplateBase tb = (TemplateBase) caller;
        TemplateBase tmpl = (TemplateBase) templateInstance_(engine).__cloneMe(engine, caller);
        tmpl.__prepareRender(tb.__curCodeType(), tb.__curLocale(), engine);
        return tmpl;
    }

    public boolean refresh() {
        return refresh(false);
    }

    public void buildSourceCode(String includingClreplacedName) {
        long start = System.currentTimeMillis();
        importPaths = new HashSet<String>();
        // Possible bug here?
        if (null != codeBuilder)
            codeBuilder.clear();
        codeBuilder = new CodeBuilder(templateResource.asTemplateContent(), name(), tagName, this, engine, dialect);
        codeBuilder.includingCName = includingClreplacedName;
        codeBuilder.build();
        extendedTemplateClreplaced = codeBuilder.getExtendedTemplateClreplaced();
        javaSource = codeBuilder.toString();
        if (logger.isTraceEnabled()) {
            logger.trace("%s ms to generate java source for template: %s", System.currentTimeMillis() - start, getKey());
        }
    }

    public void buildSourceCode() {
        long start = System.currentTimeMillis();
        importPaths = new HashSet<String>();
        // Possible bug here?
        if (null != codeBuilder) {
            codeBuilder.clear();
        }
        if (null == dialect) {
            codeBuilder = new CodeBuilder(templateResource.asTemplateContent(), name, tagName, this, engine, null);
        } else {
            codeBuilder = dialect.createCodeBuilder(templateResource.asTemplateContent(), name, tagName, this, engine);
        }
        codeBuilder.build();
        extendedTemplateClreplaced = codeBuilder.getExtendedTemplateClreplaced();
        javaSource = codeBuilder.toString();
        engine();
        if (RythmEngine.insideSandbox()) {
            javaSource = CodeBuilder.preventInfiniteLoop(javaSource);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("%s ms to generate java source for template: %s", System.currentTimeMillis() - start, getKey());
        }
    }

    public void addImportPath(String path) {
        if (path == null || path.isEmpty()) {
            return;
        }
        this.importPaths.add(path);
    }

    public void replaceImportPath(Set<String> paths) {
        this.importPaths = paths;
    }

    /**
     * @return true if this clreplaced has changes refreshed, otherwise this clreplaced has not been changed yet
     */
    public synchronized boolean refresh(boolean forceRefresh) {
        if (inner) {
            return false;
        }
        final ITemplateResource templateResource = this.templateResource;
        RythmEngine engine = engine();
        if (!templateResource.isValid()) {
            // it is removed?
            isValid = false;
            engine.clreplacedes().remove(this);
            return false;
        }
        ICodeType type = engine.renderSettings.codeType();
        if (null == type) {
            type = templateResource.codeType(engine());
        }
        if (null == type || ICodeType.DefImpl.RAW == type) {
            type = engine.conf().defaultCodeType();
        }
        codeType = type;
        if (null == name) {
            // this is the root level template clreplaced
            root = this;
            name = canonicalClreplacedName(templateResource.getSuggestedClreplacedName()) + CN_SUFFIX;
            if (engine.conf().typeInferenceEnabled()) {
                name += ParamTypeInferencer.uuid();
            }
            ITemplateResourceLoader loader = engine().resourceManager().whichLoader(templateResource);
            if (null != loader) {
                Object k = templateResource.getKey();
                tagName = toCanonicalName(k.toString(), loader.getResourceLoaderRoot());
            }
            // name = templateResource.getSuggestedClreplacedName();
            engine.registerTemplateClreplaced(this);
        }
        if (null == javaSource) {
            engine.clreplacedCache().loadTemplateClreplaced(this);
            if (null != javaSource) {
                // try refresh extended template clreplaced if there is
                Pattern p = Pattern.compile(".*extends\\s+([a-zA-Z0-9_]+)\\s*\\{\\s*\\/\\/<extended_resource_key\\>(.*)\\<\\/extended_resource_key\\>.*", Pattern.DOTALL);
                Matcher m = p.matcher(javaSource);
                if (m.matches()) {
                    String extended = m.group(1);
                    TemplateClreplacedManager tcm = engine().clreplacedes();
                    extendedTemplateClreplaced = tcm.getByClreplacedName(extended);
                    if (null == extendedTemplateClreplaced) {
                        String extendedResourceKey = m.group(2);
                        extendedTemplateClreplaced = tcm.getByTemplate(extendedResourceKey);
                        if (null == extendedTemplateClreplaced) {
                            extendedTemplateClreplaced = new TemplateClreplaced(extendedResourceKey, engine());
                            extendedTemplateClreplaced.refresh();
                        }
                    }
                    engine.addExtendRelationship(extendedTemplateClreplaced, this);
                }
            }
        }
        boolean extendedTemplateChanged = false;
        if (extendedTemplateClreplaced != null) {
            extendedTemplateChanged = extendedTemplateClreplaced.refresh(forceRefresh);
        }
        boolean includedTemplateChanged = false;
        boolean includedTemplateClreplacedesIsEmpty;
        includedTemplateClreplacedesIsEmpty = includedTemplateClreplacedes.isEmpty();
        if (includedTemplateClreplacedesIsEmpty && !S.isEmpty(includeTemplateClreplacedNames) && !NO_INCLUDE_CLreplaced.equals(includeTemplateClreplacedNames)) {
            // just loaded from persistent store
            for (String tcName : includeTemplateClreplacedNames.split(",")) {
                if (S.isEmpty(tcName)) {
                    continue;
                }
                tcName = tcName.trim();
                TemplateTestResult testResult = engine().testTemplate(tcName, this, null);
                if (null == testResult) {
                    logger.warn("Unable to load included template clreplaced from name: %s", tcName);
                    continue;
                }
                TemplateClreplaced tc = engine().getRegisteredTemplateClreplaced(testResult.getFullName());
                if (null == tc) {
                    logger.warn("Unable to load included template clreplaced from name: %s", tcName);
                    continue;
                }
                includedTemplateClreplacedes.add(tc);
            }
        }
        for (TemplateClreplaced tc : includedTemplateClreplacedes) {
            if (tc.refresh(forceRefresh)) {
                includedTemplateChanged = true;
                break;
            }
        }
        if (extendedTemplateChanged && !forceRefresh) {
            reset();
            compiled = false;
            engine().restart(new ClreplacedReloadException("extended clreplaced changed"));
            refresh(forceRefresh);
            // preplaced refresh state to sub template
            return true;
        }
        // templateResource.refresh() must be put at first so we make sure resource get refreshed
        boolean resourceChanged = templateResource.refresh();
        boolean refresh = resourceChanged || forceRefresh || (null == javaSource) || includedTemplateChanged || extendedTemplateChanged;
        if (!refresh) {
            return false;
        }
        // now start generate source and compile source to byte code
        reset();
        buildSourceCode();
        // cache source code for debugging purpose
        engine().clreplacedCache().cacheTemplateClreplacedSource(this);
        if (!codeBuilder.isRythmTemplate()) {
            isValid = false;
            engine().clreplacedes().remove(this);
            return false;
        }
        isValid = true;
        // if (!engine().isProd  Mode()) System.err.println(javaSource);
        compiled = false;
        return true;
    }

    /**
     * Is this clreplaced already compiled but not defined ?
     *
     * @return if the clreplaced is compiled but not defined
     */
    public boolean isDefinable() {
        return compiled && javaClreplaced != null;
    }

    /**
     * Remove all java source/ byte code and cache
     */
    public void reset() {
        javaByteCode = null;
        enhancedByteCode = null;
        javaSource = null;
        templateInstance = null;
        for (TemplateClreplaced tc : embeddedClreplacedes) {
            tc.reset();
            engine().clreplacedes().remove(tc);
        }
        embeddedClreplacedes.clear();
        engine().clreplacedCache().deleteCache(this);
        engine().invalidate(this);
        javaClreplaced = null;
    }

    @SuppressWarnings("unused")
    private String magic() {
        return name + magic;
    }

    /**
     * Compile the clreplaced from Java source
     *
     * @return the bytes that comprise the clreplaced file
     */
    public synchronized byte[] compile() {
        long start = System.currentTimeMillis();
        try {
            if (null != javaByteCode) {
                return javaByteCode;
            }
            if (null == javaSource) {
                throw new IllegalStateException("Cannot find java source when compiling " + getKey());
            }
            engine().clreplacedes().compiler.compile(new String[] { name });
            if (logger.isTraceEnabled()) {
                logger.trace("%sms to compile template: %s", System.currentTimeMillis() - start, getKey());
            }
            return javaByteCode;
        } catch (CompileException.CompilerException e) {
            String cn = e.clreplacedName;
            TemplateClreplaced tc = S.isEqual(cn, name) ? this : engine().clreplacedes().getByClreplacedName(cn);
            if (null == tc) {
                tc = this;
            }
            // init ce before reset java source to get template line info
            CompileException ce = new CompileException(engine(), tc, e.javaLineNumber, e.message);
            // force parser to regenerate source. This helps to reload after fixing the tag file compilation failure
            javaSource = null;
            logger.warn("compile failed for %s at line %d", tc.tagName, e.javaLineNumber);
            for (TemplateClreplaced itc : this.includedTemplateClreplacedes) {
                logger.info("\tincluded: %s", itc.tagName);
            }
            throw ce;
        } catch (NullPointerException e) {
            String clazzName = name;
            TemplateClreplaced tc = engine().clreplacedes().getByClreplacedName(clazzName);
            if (this != tc) {
                logger.error("tc is not this");
            }
            if (!this.equals(tc)) {
                logger.error("tc not match this");
            }
            logger.error("NPE encountered when compiling template clreplaced:" + name);
            throw e;
        } finally {
            if (logger.isTraceEnabled()) {
                logger.trace("%sms to compile template clreplaced %s", System.currentTimeMillis() - start, getKey());
            }
        }
    }

    /**
     * Used to instruct embedded clreplaced byte code needs to be enhanced, but for now
     * let's just use the java byte code as the enhanced bytecode
     */
    public void delayedEnhance(TemplateClreplaced root) {
        enhancedByteCode = javaByteCode;
        root.embeddedClreplacedes.add(this);
    }

    public byte[] enhance() {
        if (enhancing) {
            throw new IllegalStateException("reenter enhance() call");
        }
        enhancing = true;
        try {
            byte[] bytes = enhancedByteCode;
            if (null == bytes) {
                bytes = javaByteCode;
                if (null == bytes) {
                    bytes = compile();
                }
                long start = System.currentTimeMillis();
                IByteCodeEnhancer en = engine().conf().byteCodeEnhancer();
                if (null != en) {
                    try {
                        bytes = en.enhance(name, bytes);
                    } catch (Exception e) {
                        logger.warn(e, "Error enhancing template clreplaced: %s", getKey());
                    }
                    if (logger.isTraceEnabled()) {
                        logger.trace("%sms to enhance template clreplaced %s", System.currentTimeMillis() - start, getKey());
                    }
                }
                enhancedByteCode = bytes;
                engine().clreplacedCache().cacheTemplateClreplaced(this);
            }
            for (TemplateClreplaced embedded : embeddedClreplacedes) {
                embedded.enhancedByteCode = null;
                embedded.enhance();
            }
            return bytes;
        } finally {
            enhancing = false;
        }
    }

    /**
     * Unload the clreplaced
     */
    public void uncompile() {
        javaClreplaced = null;
    }

    public boolean isClreplaced() {
        return !name.endsWith("package-info");
    }

    public String getPackage() {
        int dot = name.lastIndexOf('.');
        return dot > -1 ? name.substring(0, dot) : "";
    }

    public void loadCachedByteCode(byte[] code) {
        enhancedByteCode = code;
    }

    /**
     * Call back when a clreplaced is compiled.
     *
     * @param code The bytecode.
     */
    public void compiled(byte[] code) {
        javaByteCode = code;
        // enhancedByteCode = code;
        compiled = true;
        RythmEvents.COMPILED.trigger(engine(), code);
        enhance();
    // compiled(code, false);
    }

    @Override
    public String toString() {
        return "(compiled:" + compiled + ") " + name;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (o instanceof TemplateClreplaced) {
            TemplateClreplaced that = (TemplateClreplaced) o;
            return that.getKey().equals(getKey());
        }
        return false;
    }

    @Override
    public int hashCode() {
        return getKey().hashCode();
    }

    private static String canonicalClreplacedName(String name) {
        if (S.empty(name)) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        char[] ca = name.toCharArray();
        int len = ca.length;
        char c = ca[0];
        if (!Character.isJavaIdentifierStart(c)) {
            sb.append('_');
        } else {
            sb.append(c);
        }
        for (int i = 1; i < len; ++i) {
            c = ca[i];
            if (!Character.isJavaIdentifierPart(c)) {
                sb.append('_');
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * Convert the key to canonical template name
     *
     * @param key  the resource key
     * @param root the resource loader root path
     * @return the canonical name
     */
    private static String toCanonicalName(String key, String root) {
        if (key.startsWith("/") || key.startsWith("\\")) {
            key = key.substring(1);
        }
        if (key.startsWith(root)) {
            key = key.replace(root, "");
        }
        if (key.startsWith("/") || key.startsWith("\\")) {
            key = key.substring(1);
        }
        // if (-1 != pos) key = key.substring(0, pos);
        key = key.replace('/', '.').replace('\\', '.');
        return key;
    }

    public static TemplateClreplaced createInnerClreplaced(String clreplacedName, byte[] byteCode, TemplateClreplaced parent) {
        TemplateClreplaced tc = new TemplateClreplaced();
        tc.name = clreplacedName;
        tc.javaByteCode = byteCode;
        // tc.enhancedByteCode = byteCode;
        tc.inner = true;
        tc.root = parent.root();
        return tc;
    }

    public ITemplateResource getTemplateResource() {
        return templateResource;
    }

    public ICodeType getCodeType() {
        return codeType;
    }

    public Set<String> getImportPaths() {
        if (null == importPaths) {
            return Collections.emptySet();
        }
        return Collections.unmodifiableSet(importPaths);
    }

    public String getJavaSource() {
        return javaSource;
    }

    @Deprecated
    public void setJavaPackage(Package javaPackage) {
        this.javaPackage = javaPackage;
    }

    @Deprecated
    public void setJavaClreplaced(Clreplaced<ITemplate> javaClreplaced) {
        this.javaClreplaced = javaClreplaced;
    }

    public CodeBuilder getCodeBuilder() {
        return codeBuilder;
    }

    public Clreplaced<ITemplate> getJavaClreplaced() {
        return javaClreplaced;
    }

    public byte[] getEnhancedByteCode() {
        return enhancedByteCode;
    }

    public byte[] getJavaByteCode() {
        return javaByteCode;
    }

    public int getSigChecksum() {
        return sigChecksum;
    }

    @Deprecated
    public void setJavaSource(String javaSource) {
        this.javaSource = javaSource;
    }

    @Deprecated
    public void setExtendedTemplateClreplaced(TemplateClreplaced extendedTemplateClreplaced) {
        this.extendedTemplateClreplaced = extendedTemplateClreplaced;
    }

    public void setIncludeTemplateClreplacedNames(String includeTemplateClreplacedNames) {
        this.includeTemplateClreplacedNames = includeTemplateClreplacedNames;
    }
}

16 View Complete Implementation : TemplateResourceManager.java
Copyright Apache License 2.0
Author : rythmengine
public TemplateClreplaced tryLoadTemplate(String tmplName, TemplateClreplaced callerClreplaced, ICodeType codeType) {
    if (blackList.contains(tmplName)) {
        // logger.info(">>> %s is in the black list", tmplName);
        return null;
    }
    TemplateClreplaced tc = null;
    RythmEngine engine = this.engine;
    if (null != callerClreplaced) {
        ITemplateResourceLoader loader = whichLoader(callerClreplaced.templateResource);
        if (null != loader) {
            return loader.tryLoadTemplate(tmplName, engine, callerClreplaced, codeType);
        }
    }
    for (ITemplateResourceLoader loader : loaders) {
        tc = loader.tryLoadTemplate(tmplName, engine, callerClreplaced, codeType);
        if (null != tc) {
            break;
        }
    }
    return tc;
}