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

com.greenlaw110.rythm.conf.RythmConfigurationKey Maven / Gradle / Ivy

Go to download

A strong typed high performance Java Template engine with .Net Razor like syntax

The newest version!
/* 
 * Copyright (C) 2013 The Rythm Engine project
 * Gelin Luo 
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/
package com.greenlaw110.rythm.conf;

import com.greenlaw110.rythm.Rythm;
import com.greenlaw110.rythm._Rythm;
import com.greenlaw110.rythm.cache.NoCacheService;
import com.greenlaw110.rythm.cache.SimpleCacheService;
import com.greenlaw110.rythm.exception.ConfigurationException;
import com.greenlaw110.rythm.extension.ICodeType;
import com.greenlaw110.rythm.extension.IDurationParser;
import com.greenlaw110.rythm.extension.II18nMessageResolver;
import com.greenlaw110.rythm.logger.JDKLogger;
import com.greenlaw110.rythm.utils.S;

import java.io.File;
import java.net.URL;
import java.util.*;

/**
 * {@link com.greenlaw110.rythm.RythmEngine} configuration keys. General rules:
 * 

*

    *
  • When a key is ended with .enabled, then you should be able to set * the setting without .enabled or replace it with .disabled * but the value will be inverted. For example, built_in.transformer.enabled * is equal to built_in.transformer and invert to * built_in.transformer.disabled
  • *
  • When a key is ended with .impl, then you can either put an instance into * the configuration map or a string of the class name
  • *
*/ public enum RythmConfigurationKey { /** * "built_in.code_type.enabled": Enable built-in {@link com.greenlaw110.rythm.extension.ICodeType code type} implementations *

*

Default value: true

*/ BUILT_IN_CODE_TYPE_ENABLED("built_in.code_type.enabled", true), /** * "built_in.transformer.enabled": Enable built-in {@link com.greenlaw110.rythm.extension.Transformer transformer} implementations *

*

Default value: true

* * @see #FEATURE_TRANSFORM_ENABLED */ BUILT_IN_TRANSFORMER_ENABLED("built_in.transformer.enabled", true), /** * "cache.enabled": Enable disable {@link com.greenlaw110.rythm.extension.ICacheService cache service}. When this * setting is turned off, the {@link #CACHE_SERVICE_IMPL} will be set to * {@link com.greenlaw110.rythm.cache.NoCacheService} without regarding to it's configuration *

*

Default value: false

*

* TODO: add link to cache service reference */ CACHE_ENABLED("cache.enabled", false), /** * "cache.service.impl": Set {@link com.greenlaw110.rythm.extension.ICacheService cache service} implementation *

*

Default value: {@link com.greenlaw110.rythm.cache.SimpleCacheService}

*

*

Note when {@link #CACHE_ENABLED} is set to false, then this setting * will be ignored, and the service impl will be set to {@link com.greenlaw110.rythm.cache.NoCacheService} * anyway

*

* TODO: add link to cache service reference */ CACHE_SERVICE_IMPL("cache.service.impl") { @Override protected Object getDefVal(Map configuration) { Boolean cacheEnabled = CACHE_ENABLED.getConfiguration(configuration); return cacheEnabled ? SimpleCacheService.INSTANCE : NoCacheService.INSTANCE; } }, /** * "cache.duration_parser.impl": set {@link com.greenlaw110.rythm.extension.IDurationParser duration parser} implementation. *

*

Default value: {@link com.greenlaw110.rythm.extension.IDurationParser#DEFAULT_PARSER}

*/ CACHE_DURATION_PARSER_IMPL("cache.duration_parser.impl", IDurationParser.DEFAULT_PARSER), /** * "cache.prod_only.enabled": Turn on/off cache at * {@link com.greenlaw110.rythm.Rythm.Mode#dev dev} mode. When * this setting is turned on, then cache will not effect at dev mode *

*

Default value: true

*/ CACHE_PROD_ONLY_ENABLED("cache.prod_only.enabled", true), /** * "codegen.compact.enabled": Enable/disable compact redundant space and lines *

*

Default value: true

*/ CODEGEN_COMPACT_ENABLED("codegen.compact.enabled", true), /** * "codegen.source_code_enhancer.impl": Set template * {@link com.greenlaw110.rythm.extension.ISourceCodeEnhancer source code enhancer} * implementation. *

Default value: null

*/ CODEGEN_SOURCE_CODE_ENHANCER("codegen.source_code_enhancer.impl"), /** * "codegen.byte_code_enhancer.impl": Set template * {@link com.greenlaw110.rythm.extension.IByteCodeEnhancer byte code enhancer} implementation. *

Default value: null

*/ CODEGEN_BYTE_CODE_ENHANCER("codegen.byte_code_enhancer.impl"), /** * "default.code_type.impl": Set default {@link com.greenlaw110.rythm.extension.ICodeType code type} *

*

Default value: {@link com.greenlaw110.rythm.extension.ICodeType.DefImpl#RAW raw}

*

* TODO: what if {@link #BUILT_IN_CODE_TYPE_ENABLED} is false */ DEFAULT_CODE_TYPE_IMPL("default.code_type.impl", ICodeType.DefImpl.RAW), /** * "default.cache_ttl": Set default {@link com.greenlaw110.rythm.extension.ICacheService cache} ttl * in second *

*

Default value: 60 * 60(1hr

*/ DEFAULT_CACHE_TTL("default.cache_ttl") { public T getConfiguration(Map configuration) { String k = getKey(); Object v = configuration.get(k); if (null == v) { return (T) (Number) (60 * 60); } if (v instanceof Number) { return (T) v; } return (T) (Integer.valueOf(v.toString())); } }, /** * "engine.mode": Set the {@link com.greenlaw110.rythm.Rythm.Mode mode} of rythm engine *

Default value: {@link com.greenlaw110.rythm.Rythm.Mode#prod}

*/ ENGINE_MODE("engine.mode") { @Override public T getConfiguration(Map configuration) { String k = getKey(); Object v = configuration.get(k); if (null == v) { return (T) Rythm.Mode.prod; } else { if (v instanceof Rythm.Mode) { return (T) v; } else { return (T) Rythm.Mode.valueOf(v.toString()); } } } }, /** * "engine.id": Set the ID of rythm engine instance *

Default value: "re-" plus a random String with 3 chars

*/ ENGINE_ID("engine.id") { @Override protected Object getDefVal(Map configuration) { return "re-" + S.random(3); } }, /** * "engine.class_loader.parent.impl": Set the {@link ClassLoader#getParent() parent} class loader of the rythm * template class loader *

Default value: first try to use {@link Thread#getContextClassLoader() current thread's context class loader} * if the context classloader is null, then use the class loader which loads the Rythm.class

*/ ENGINE_CLASS_LOADER_PARENT_IMPL("engine.class_loader.parent.impl") { @Override protected Object getDefVal(Map configuration) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (null == cl) { cl = Rythm.class.getClassLoader(); } return cl; } }, /** * "engine.class_loader.byte_code_helper.impl": Set the {@link com.greenlaw110.rythm.extension.IByteCodeHelper bytecode helper} * implementation *

Default value: null

*/ ENGINE_CLASS_LOADER_BYTE_CODE_HELPER_IMPL("engine.class_loader.byte_code_helper.impl"), /** * "engine.load_precompiled.enabled": Set the flag so that Rythm will load precompiled template class directly from * bytecode cached in the {@link #HOME_PRECOMPILED precompiled root} when running * in {@link com.greenlaw110.rythm.Rythm.Mode#prod prod} mode. *

Default value: false

*/ ENGINE_LOAD_PRECOMPILED_ENABLED("engine.load_precompiled.enabled", false), /** * "engine.file_write.enabled": Enable/disable write to file system. This option is used by rythm to check if * it should write template class bytecode cache to disk or not. In some cases * you want to disable file write due the limit of the runtime environment, e.g. * on GAE platform *

*

Default value: true

*/ ENGINE_FILE_WRITE_ENABLED("engine.file_write.enabled", true), /** * "engine.precompile_mode.enabled": Set/unset precompile mode. This option is used by play-rythm plugin (could also * be other plugin) to notify rythm that is is doing a precompile. User application * should not use this option *

*

Default value: false

*/ ENGINE_PRECOMPILE_MODE("engine.precompile_mode.enabled") { @Override public T getConfiguration(Map configuration) { String k = getKey(); Object v = configuration.get(k); if (null == v) { return (T) Boolean.FALSE; } else { if (v instanceof Boolean) { return (T) v; } else { return (T) Boolean.valueOf(v.toString()); } } } }, ENGINE_OUTPUT_JAVA_SOURCE_ENABLED("engine.debug_java_source.enabled", false), /** * "engine.playframework.enabled": A special flag used when Rythm is working with rythm-plugin for Play!Framework. Usually * you should not touch this setting. *

*

Default value: false

*/ ENGINE_PLAYFRAMEWORK("engine.playframework.enabled", false), /** * "engine.plugin.version": Set by plugin of certain framework, e.g. play!framework. Used to determine * whether it needs to refresh the cached template class bytecode. Default value: "" (empty string) */ ENGINE_PLUGIN_VERSION("engine.plugin.version", ""), /** * "feature.transform.enabled": Enable disable {@link com.greenlaw110.rythm.extension.Transformer transformer} *

*

Default value: true

*/ FEATURE_TRANSFORM_ENABLED("feature.transform.enabled", true), /** * "feature.type_inference.enabled": Enable disable type inference. TODO add link to type inference reference page *

*

Default value: false

*/ FEATURE_TYPE_INFERENCE_ENABLED("feature.type_inference.enabled", false), /** * "feature.smart_escape.enabled": Enable disable smart escape. TODO: add link to smart escape reference page *

*

Default value: true

*/ FEATURE_SMART_ESCAPE_ENABLED("feature.smart_escape.enabled", true), /** * "feature.natural_template.enabled": Enable disable natural template. TODO: add reference link to natural template *

*

Default value: true

*/ FEATURE_NATURAL_TEMPLATE_ENABLED("feature.natural_template.enabled", false), /** * "home.template.dir": Set the home dir of template files. This configuration is used when the {@link #RESOURCE_LOADER_IMPL} * is not configured, therefore the {@link com.greenlaw110.rythm.resource.TemplateResourceManager} will * try to load {@link com.greenlaw110.rythm.resource.FileTemplateResource} from this template home dir * configured. *

*

Default value: a file created with the following logic

*

*

new File(Thread.currentThread().getContextClassLoader().getResource("rythm").getFile())
*/ HOME_TEMPLATE("home.template.dir") { @Override protected Object getDefVal(Map configuration) { URL url = Thread.currentThread().getContextClassLoader().getResource("rythm"); if (null != url) return new File(url.getPath()); return new File("rythm"); } }, /** * "home.tmp.dir": Set the rythm tmp dir. The tmp dir is to where Rythm write compiled template class bytecode * when running in the {@link com.greenlaw110.rythm.Rythm.Mode#dev dev} mode. *

*

Default value: a file created with the following logic

*

*

new File(System.__getProperty("java.io.tmpdir"), "__rythm")
*/ HOME_TMP("home.tmp.dir") { @Override protected Object getDefVal(Map configuration) { return new File(System.getProperty("java.io.tmpdir"), "__rythm"); } }, /** * "home.precompiled.dir": Set the dir root of the precompiled template bytecodes. Default value: null * * @see #ENGINE_LOAD_PRECOMPILED_ENABLED */ HOME_PRECOMPILED("home.precompiled.dir") { @Override protected Object getDefVal(Map configuration) { return null; } }, /** * "i18n.locale": the locale for the rythm runtime environment. This configuration * return the {@link java.util.Locale} type of instance. * *

Default value: java.util.Locale.getDefault()

* * @see Java Locale */ I18N_LOCALE("i18n.locale") { @Override public T getConfiguration(Map configuration) { String k = getKey(); Object o = configuration.get(k); if (o instanceof Locale) { return (T)o; } // check lang_REGION style String s = S.str(o); if (S.empty(s)) { return (T)Locale.getDefault(); } Locale retval; String[] sa = s.split("_"); String lang = sa[0]; if (sa.length > 1) { String region = sa[1]; retval = new Locale(lang, region); } else { retval = new Locale(lang); } return (T)retval; } }, /** * "i18n.message.sources": Set message sources. Should be a String of message (resource bundle) properties * file names separated by ",", E.g. "format,exception,windows". *

Default value: message

* * @see [Spring]Internationalization using MessageSource */ I18N_MESSAGE_SOURCES("i18n.message.sources", "messages"), /** * "i18n.message.resolver.impl": Set i18n message resolver. Should implement {@link com.greenlaw110.rythm.extension.II18nMessageResolver} * interface. Default value: {@link com.greenlaw110.rythm.extension.II18nMessageResolver.DefaultImpl#INSTANCE}, which delegate * to {@link com.greenlaw110.rythm.utils.S#i18n(com.greenlaw110.rythm.template.ITemplate, String, Object...)} method */ I18N_MESSAGE_RESOLVER("i18n.message.resolver.impl", II18nMessageResolver.DefaultImpl.INSTANCE), /** * "log.enabled": Enable disable log in Rythm. Default value: true */ LOG_ENABLED("log.enabled", true), /** * "log.factory.impl": Configure the {@link com.greenlaw110.rythm.extension.ILoggerFactory logger factory} implementation. * When this configuration is not set, then a {@link com.greenlaw110.rythm.logger.JDKLogger.Factory} instance * is used to create the logger *

*

Default value: com.greenlaw110.rythm.logger.JDKLogger.Factory

*/ LOG_FACTORY_IMPL("log.factory.impl", JDKLogger.Factory.class), /** * "log.source.java.enabled": Print out relevant java source lines when exception encountered *

*

Default value: true

*/ LOG_SOURCE_JAVA_ENABLED("log.source.java.enabled", true), /** * "log.source.template.enabled": Print out relevant template source lines when exception encountered *

*

Default value: true

*/ LOG_SOURCE_TEMPLATE_ENABLED("log.source.template.enabled", true), /** * "log.time.render.enabled": Log time spent executing a template. The level used to log the time logRenderTime * is {@link com.greenlaw110.rythm.logger.ILogger#debug(String, Object...)} *

*

Default value: false

*/ LOG_TIME_RENDER_ENABLED("log.time.render.enabled", false), /** * "render.listener.impl": Set {@link com.greenlaw110.rythm.extension.IRythmListener tag * invocation listener} implementation. *

Default value: null

*/ RENDER_LISTENER("render.listener.impl"), /** * "render.exception_handler.impl": Set {@link com.greenlaw110.rythm.extension.IRenderExceptionHandler * render exception handler} implementation. *

Default value: null

*/ RENDER_EXCEPTION_HANDLER("render.exception_handler.impl"), /** * "resource.loader.impl": The {@link com.greenlaw110.rythm.extension.ITemplateResourceLoader resource loader} * implementation *

Default value: null. But if this is not configured, try templates will be loaded as * {@link com.greenlaw110.rythm.resource.FileTemplateResource file template resource} first and if * still not found then try to load as * {@link com.greenlaw110.rythm.resource.ClasspathTemplateResource classpath resource}.

* * @see #HOME_TEMPLATE */ RESOURCE_LOADER_IMPL("resource.loader.impl"), /** * "resource.name.suffix": does resource name has special rythm suffix attached? * E.g. .rythm or .rtl etc. Default is empty string */ RESOURCE_NAME_SUFFIX("resource.name.suffix", "") { @Override public T getConfiguration(Map configuration) { String s = super.getConfiguration(configuration); if (S.empty(s)) return (T)""; if (!s.startsWith(".")) s = "." + s; return (T)s; } }, /** * "sandbox.security_manager.impl": Set the security manager to be used when running a template in * {@link com.greenlaw110.rythm.Sandbox sandbox} mode. *

Default value: null. When no security manager is configured, when the sandbox mode is running, an * instance of {@link com.greenlaw110.rythm.sandbox.RythmSecurityManager} will be initiated to supervise the * execution. Usually you should NOT set this configuration and allow Rythm to run it's SecurityManager * implementation.

*/ SANDBOX_SECURITY_MANAGER_IMPL("sandbox.security_manager.impl"), /** * "sandbox.timeout": Set the timeout of a {@link com.greenlaw110.rythm.Sandbox sandbox} execution in milliseconds. * If the execution failed to return after timeout, then Rythm will interrupt the execution thread and force it * to return. This setting prevent infinite loop in untrusted template. *

Default value: 1000

*/ SANDBOX_TIMEOUT("sandbox.timeout") { @Override public T getConfiguration(Map configuration) { String k = getKey(); Object v = configuration.get(k); if (null == v) { return (T) (Integer) 2000; } if (v instanceof Number) { return (T) v; } return (T) Integer.valueOf(v.toString()); } }, /** * "sandbox.pool.size": Set the thread pool size of {@link com.greenlaw110.rythm.Sandbox sandbox} executors. *

Default value: 10

*/ SANDBOX_POOL_SIZE("sandbox.pool.size") { @Override public T getConfiguration(Map configuration) { String k = getKey(); Object v = configuration.get(k); if (null == v) { return (T) (Integer) 10; } if (v instanceof Number) { return (T) v; } return (T) Integer.valueOf(v.toString()); } }, /** * "sandbox.restricted_class": Set restricted classes for {@link com.greenlaw110.rythm.Sandbox sandbox} execution. * The value should be full name of the classes or packages separated by ;. For example, * "foo.bar.Employee;foo.secure;...". *

* If a class or package name is presented in this setting, then the sandbox executor will raise a * {@link SecurityException} when the template trying to access the class. Note whatever this setting is * configured, Rythm will prevent the access to the following classes/packages: *

*
    *
  • com.greenlaw110.rythm.Rythm;
  • *
  • com.greenlaw110.rythm.RythmEngine;
  • *
  • java.io;
  • *
  • java.nio;
  • *
  • java.security;
  • *
  • java.rmi;
  • *
  • java.net;
  • *
  • java.awt;
  • *
  • java.applet
  • *
* Default value: "" */ SANDBOX_RESTRICTED_CLASS("sandbox.restricted_class", ""), /** * "sandbox.allowed_system_properties": Set allowed system properties in string separated by ,. * * By default the following properties are allowed to access by sandbox thread *
    *
  • user.dir
  • *
  • line.separator
  • *
  • java.vm.name
  • *
  • java.protocol.handler.pkgs
  • *
*/ SANDBOX_ALLOWED_SYSTEM_PROPERTIES("sandbox.allowed_system_properties", "java.io.tmpdir,file.encoding,user.dir,line.separator,java.vm.name,java.protocol.handler.pkgs,suppressRawWhenUnchecked"), /** * "sandbox.thread_factory.impl": Configure the thread factory to be used by the sandbox executing service. *

Note this configuration should be very rare used as it is create to support rythmfiddle implementation. * Should you really need to configure this item, make sure it is configured as an instance of {@link com.greenlaw110.rythm.sandbox.SandboxThreadFactory}

*

Default value: null

*/ SANBOX_THREAD_FACTORY_IMPL("sandbox.thread_factory.impl", null), /** * "transformer.udt": User defined transformers, should be a list of class names separated by ",". If configured * then {@link com.greenlaw110.rythm.RythmEngine#registerTransformer(Class[]) RythmEngine.registerTransformer} will * be called to register these user defined transformer classes. Default value: null */ TRANSFORMER_UDT("transformer.udt"); private String key; private Object defVal; private RythmConfigurationKey(String key) { this(key, null); } private RythmConfigurationKey(String key, Object defVal) { this.key = key; this.defVal = defVal; } /** * Return the key string * * @return the key of the configuration */ public String getKey() { return key; } /** * Return default value of this setting. The configuration data map * is passed in in case the default value be variable depending on * another setting. For example, the default value of {@link #HOME_TMP tmp dir} * setting depend on the value of {@link #ENGINE_MODE mode} setting * * @param configuration * @return return the default value */ protected Object getDefVal(Map configuration) { return defVal; } /** * Calling to this method is equals to calling {@link #getKey()} * * @return key of the configuration */ @Override public String toString() { return key; } private static List aliases(String key, String suffix) { List l = new ArrayList(); l.add("rythm." + key); l.add(key); if (S.notEmpty(suffix)) { String k0 = key.replace("." + suffix, ""); l.add("rythm." + k0); l.add(k0); } return l; } private Object getValFromAliases(Map configuration, String key, String suffix) { Object v = configuration.get(key); if (null == v) { for (String k0 : aliases(key, suffix)) { v = configuration.get(k0); if (null != v) break; } if (null == v) { // still not found, load default value v = getDefVal(configuration); } } return v; } private static boolean toBoolean(Object v) { if (null == v) return false; if (v instanceof Boolean) return (Boolean)v; return Boolean.parseBoolean(v.toString()); } private Boolean getEnabled(String key, Map configuration) { Object v = getValFromAliases(configuration, key, "enabled"); if (null == v) { v = getValFromAliases(configuration, key, "disabled"); return !toBoolean(v); } return toBoolean(v); } private T getImpl(String key, Map configuration) { Object v = getValFromAliases(configuration, key, "impl"); if (null == v) return null; if (v instanceof Class) { try { return (T) ((Class) v).newInstance(); } catch (Exception e) { throw new ConfigurationException(e, "Error getting implementation configuration: %s", key); } } if (!(v instanceof String)) return (T)v; String clsName = (String)v; try { return (T) Class.forName(clsName).newInstance(); } catch (Exception e) { // try to evaluate the string try { Object o = _Rythm.eval(clsName); if (o instanceof Class) { return (T) ((Class) o).newInstance(); } else { return (T) o; } } catch (Exception e1) { throw new ConfigurationException(e, "Error getting implementation configuration: %s", key); } } } private File getFile(String key, Map configuration) { Object v = getValFromAliases(configuration, key, "dir"); if (null == v) return null; if (v instanceof File) { return (File) v; } String s = v.toString(); boolean isAbsolute = false; if (s.startsWith("/") || s.startsWith(File.separator)) { isAbsolute = true; } else if (s.matches("^[a-zA-Z]:.*")) { isAbsolute = true; } if (isAbsolute) return new File(s); try { URL url = Thread.currentThread().getContextClassLoader().getResource(s); return new File(url.getPath()); } catch (Exception e) { throw new ConfigurationException(e, "Error reading file configuration %s", key); } } /** * Return configuration value from the configuration data map using the {@link #key} * of this {@link RythmConfigurationKey setting} instance * * @param configuration * @param * @return return the configuration */ public T getConfiguration(Map configuration) { String key = this.key; if (key.endsWith(".enabled")) { return (T) getEnabled(key, configuration); } if (key.endsWith(".impl")) { return getImpl(key, configuration); } if (key.endsWith(".dir")) { return (T) getFile(key, configuration); } return (T) getValFromAliases(configuration, key, null); } /** * Return default configuration of this item * * @param * @return default configuration for this item */ public T getDefaultConfiguration() { return (T)getConfiguration((Map)Collections.emptyMap()); } private static Map lookup = new HashMap(50); static { for (RythmConfigurationKey k : values()) { lookup.put(k.getKey().toLowerCase(), k); } } /** * Return key enum instance from the string in case insensitive mode * * @param s * @return configuration key from the string */ public static RythmConfigurationKey valueOfIgnoreCase(String s) { if (S.empty(s)) throw new IllegalArgumentException(); return lookup.get(s.trim().toLowerCase()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy