package act.conf;
/*-
* #%L
* ACT Framework
* %%
* Copyright (C) 2014 - 2017 ActFramework
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import act.Act;
import act.app.App;
import act.handler.UnknownHttpMethodProcessor;
import act.view.TemplatePathResolver;
import act.view.View;
import org.osgl.$;
import org.osgl.exception.NotAppliedException;
import org.osgl.util.E;
import org.osgl.util.S;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* {@link App} configuration keys. General rules:
* <p/>
* <ul>
* <li>When a key is ended with <code>.enabled</code>, then you should be able to set
* the setting without <code>.enabled</code> or replace it with <code>.disabled</code>
* but the value will be inverted. For example, <code>built_in.transformer.enabled</code>
* is equal to <code>built_in.transformer</code> and invert to
* <code>built_in.transformer.disabled</code></li>
* <p/>
* <li>When a key is ended with <code>.impl</code>, then you can either put an instance into
* the configuration map or a string of the class className</li>
* </ul>
*/
public enum AppConfigKey implements ConfigKey {
/**
* {@code act.basic_authentication.enabled} turn on/off Basic Authentication
* in Act application.
*
* Default value: `false`
*
* **Note** there is no logic around this configuration in the core
* ActFramework. It is up to the security plugins like `act-aaa-plugin`
* to favor the value of this setting
*/
BASIC_AUTHENTICATION("basic_authentication.enabled"),
/**
* {@code act.cache.impl}
* Specify {@link org.osgl.cache.CacheServiceProvider Cache service provider}
* <p>Default value: {@link org.osgl.cache.CacheServiceProvider.Impl#Simple the simple
* in memory map based cache service implementation}</p>
*/
CACHE_IMPL("cache.impl"),
/**
* {@code act.cache.name}
*
* Specify the default cache name
*
* Default value: `_act_app_`
*/
CACHE_NAME("cache.name"),
/**
* {@code act.cache.name.session}
*
* Specify the session cache name
*
* Default value: the value configured by {@link #CACHE_NAME}
*/
CACHE_NAME_SESSION("cache.name.session"),
/**
* {@code act.cli.enabled}
*
* Turn on/off CLI server support
*
* Default value: {@code true}
*/
CLI_ENABLED("cli.enabled"),
/**
* {@code act.cli.port} specifies the default cli (telnet) port the application
* listen to.
* <p>Default value: {@code 5461}</p>
*/
CLI_PORT("cli.port"),
/**
* {@code act.cli.json.page.size}
* Specify the maximum records in one page for JSON layout by CLI command
*
* Default value: 10
*/
CLI_PAGE_SIZE_JSON("cli.page.size.json"),
/**
* {@code act.cli.table.page.size}
* Specify the maximum records in one page for table layout by CLI command
*
* Default value: 22
*/
CLI_PAGE_SIZE_TABLE("cli.page.size.table"),
/**
* {@code cli.session.expiration} specifies the number of seconds
* a cli session can exists after last user interaction
* <p>Default value: {@code 300} seconds. e.g. 5 minutes</p>
*/
CLI_SESSION_EXPIRATION("cli.session.expiration"),
/**
* {@code cli.session.max} specifies the maximum number of cli threads
* can exists concurrently
* <p>Default value: {@code 3}</p>
*/
CLI_SESSION_MAX("cli.session.max"),
/**
* `act.cli_over_http.enabled` turn on/off CLI over http feature, which
* allows ActFramework to handle http request sent through to the {@link #CLI_OVER_HTTP_PORT}
* as a way to invoke CLI commands and inspect results
*
* Default value: `false`
*/
CLI_OVER_HTTP("cli_over_http.enabled"),
/**
* `act.cli_over_http.authority` specifies the {@link act.cli.CliOverHttpAuthority} implementation
*/
CLI_OVER_HTTP_AUTHORITY("cli_over_http.authority.impl"),
/**
* `act.cli_over_http.port` specifies the default cli over http port the application
* listen to.
*
* Default value: `5462`
*/
CLI_OVER_HTTP_PORT("cli_over_http.port"),
/**
* `act.cli_over_http.port` specify the title to be displayed on the CLI Over Http
* page
*
* Default value: "Cli Over Http"
*/
CLI_OVER_HTTP_TITLE("cli_over_http.title"),
/**
* `act.cli_over_http.syscmd.enabled` turn on/off system command on CLI Over Http
* page
*
* Default value: `true`
*/
CLI_OVER_HTTP_SYS_CMD("cli_over_http.syscmd.enabled"),
/**
* `act.cookie.domain_provider.impl` specify the provider
* that provides the cookie domain name
*
* Default value: value of {@link #HOST}
*/
COOKIE_DOMAIN_PROVIDER("cookie.domain_provider.impl"),
/**
* {@code cookie.prefix} specifies the prefix to be prepended
* to the different cookie names e.g. session cookie, flash cookie,
* locale cookie etc. Let's say the default cookie name is
* {@code act_session}, and user specifies the prefix {@code my_app}
* then the session cookie name will be {@code my_app_session}.
* <p>Note this setting also impact the {@link AppConfig#flashCookieName()}</p>
* <p>Default value: {@code act}</p>
*/
COOKIE_PREFIX("cookie.prefix"),
/**
* {@code act.cors.enabled} turn on/off CORS in Act application
*
* Default value: `false`
*/
CORS("cors.enabled"),
/**
* `act.cors.option.check` specify whether the framework should
* check the current request is an HTTP OPTION method before applying
* controller headers or not
*
* default value: `true`
*/
CORS_CHECK_OPTION_METHOD("cors.option.check.enabled"),
/**
* {@code act.cors.origin} specifies `Access-Control-Allow-Origin` header
* to be output
*
* Default value: `*`
*/
CORS_ORIGIN("cors.origin"),
/**
* {@code act.cors.headers} specifies both `Access-Control-Expose-Headers`
* and `Access-Control-Allow-Headers`
*
* Default value: `Content-Type, X-HTTP-Method-Override`
*/
CORS_HEADERS("cors.headers"),
/**
* {@code act.cors.headers.expose} specify `Access-Control-Expose-Headers`.
* Note this setting will overwrite the setting of {@link #CORS_HEADERS} if
* it is set
*
* Default value: empty
*/
CORS_HEADERS_EXPOSE("cors.headers.expose"),
/**
* {@code act.cors.headers.expose} specify `Access-Control-Allow-Headers`.
* Note this setting will overwrite the setting of {@link #CORS_HEADERS} if
* it is set
*
* Default value: empty
*/
CORS_HEADERS_ALLOWED("cors.headers.allowed"),
/**
* {@code act.cors.max_age} specifies `Access-Control-Max-Age`.
*
* Default value: 30*60 (seconds)
*/
CORS_MAX_AGE("cors.max_age"),
/**
* `act.cors.allow_credential` specifies `Access-Control-Allow-Credential`.
*
* Default value: `false`
*/
CORS_ALLOW_CREDENTIALS("cors.allow_credentials.enabled"),
/**
* {@code act.content_suffix.aware.enabled}
* <p>
* Once enabled then the framework automatically recognize request with content suffix.
* E.g. {@code /customer/123/json} or {@code /customer/123.json} will match the
* route {@code /customer/123} and set the request {@code Accept} header to
* {@code application/json}
* </p>
* <p>Default value: {@code false}</p>
*/
CONTENT_SUFFIX_AWARE("content_suffix.aware.enabled"),
/**
* {@code act.csrf.enabled} turn on/off global CSRF protect
*
* Default value: `true`
*/
CSRF("csrf.enabled"),
/**
* {@code act.csrf.param_name} specifies the http request param name
* used to convey the csrf token
*
* Default value: the value of {@link act.app.ActionContext#ATTR_CSRF_TOKEN}
*/
CSRF_PARAM_NAME("csrf.param_name"),
/**
* {@code act.csrf.header_name} specifies name of the http request
* header used to convey the csrf token sent from AJAX client.
*
* Default value: `X-Xsrf-Token` - the name used by AngularJs
*/
CSRF_HEADER_NAME("csrf.header_name"),
/**
* {@code act.csrf.cookie_name} specify the name of the cookie used
* to convey the csrf token generated on the server for the first GET
* request coming from a client.
*
* Default value: `XSRF-TOKEN` - the name used by AngularJs
*/
CSRF_COOKIE_NAME("csrf.cookie_name"),
/**
* `act.csrf.protector.impl` specifies the implementation of
* {@link act.security.CSRFProtector}.
*
* The value of this configuration could be either a name of
* the class that implements {@link act.security.CSRFProtector}
* interface, or the enum name of {@link act.security.CSRFProtector.Predefined}
*
* Default value: `HMAC` which specifies the {@link act.security.CSRFProtector.Predefined#HMAC}
*/
CSRF_PROTECTOR("csrf.protector.impl"),
/**
* `act.db.seq_gen.impl` specifies the implementation of
* {@link act.db.util._SequenceNumberGenerator}.
*
* Default value: `null`
*/
DB_SEQ_GENERATOR("db.seq_gen.impl"),
/**
* `dsp.token` specifies the name of "double submission protect token"
*
* Default value: `act_dsp_token`
*/
DOUBLE_SUBMISSION_PROTECT_TOKEN("dsp.token"),
/**
* {@code act.encoding} specifies application default encoding
* <p>Default value: utf-8</p>
*/
ENCODING("encoding"),
/**
* `act.enum.resolving.case_sensitive` specifies whether it
* allow enum resolving for request parameters to ignore case
*
* Default value: `false` meaning enum resolving is case insensitive
*/
ENUM_RESOLVING_CASE_SENSITIVE("enum.resolving.case_sensitive"),
/**
* {@code act.fmt.date} specifies the default date format used to
* lookup/output the date string
* <p>Default value: the pattern of {@code java.text.DateFormat.getDateInstance()}</p>
*/
FORMAT_DATE("fmt.date"),
/**
* {@code act.fmt.date} specifies the default date and time format used to
* lookup/output the date string
* <p>Default value: the pattern of {@code java.text.DateFormat.getDateTimeInstance()}</p>
*/
FORMAT_DATE_TIME("fmt.date_time"),
/**
* {@code act.fmt.time} specifies the default time format used to
* lookup/output the date time string
* <p>Default value: the pattern of {@code java.text.DateFormat.getTimeInstance()}</p>
*/
FORMAT_TIME("fmt.time"),
/**
* `act.handler.csrf_check_failure.impl` specifies the implementation
* for {@link act.util.MissingAuthenticationHandler}
*
* Default value: {@link act.util.RedirectToLoginUrl}
*/
HANDLER_CSRF_CHECK_FAILURE("handler.csrf_check_failure.impl"),
/**
* `act.handler.csrf_check_failure.ajax.impl` specifies the implementation for
* {@link act.util.MissingAuthenticationHandler} dealing with the case of AJAX
* request
*
* Default value: the value of {@link #HANDLER_CSRF_CHECK_FAILURE}
*/
HANDLER_AJAX_CSRF_CHECK_FAILURE("handler.csrf_check_failure.ajax.impl"),
/**
* {@code handler.missing_authentication.impl} specifies the implementation
* for {@link act.util.MissingAuthenticationHandler}
* <p>Default value: {@link act.util.RedirectToLoginUrl}</p>
*/
HANDLER_MISSING_AUTHENTICATION("handler.missing_authentication.impl"),
/**
* {@code handler.missing_authentication.ajax.impl} specifies the implementation
* for {@link act.util.MissingAuthenticationHandler} dealing with the case of AJAX
* request
* <p>Default value: the value of {@link #HANDLER_MISSING_AUTHENTICATION}</p>
*/
HANDLER_MISSING_AUTHENTICATION_AJAX("handler.missing_authentication.ajax.impl"),
/**
* {@code unknown_http_method_handler} specifies a class/instance that
* implements {@link UnknownHttpMethodProcessor} that process
* the HTTP methods that are not recognized by {@link act.route.Router},
* e.g. "OPTION", "PATCH" etc
*/
HANDLER_UNKNOWN_HTTP_METHOD("handler.unknown_http_method.impl"),
/**
* {@code act.host} specifies the host the application
* reside on.
* <p/>
* <p>Default value: {@code localhost}</p>
*/
HOST("host"),
/**
* `act.http.external_server.enabled` specify if the app is running behind a front end
* http server
*
* Default value: `true` when running in PROD mode; `false` when running in DEV mode
*/
HTTP_EXTERNAL_SERVER("http.external_server.enabled"),
/**
* {@code act.http.params.max} specifies the maximum number of http parameters
* this is to prevent the hash collision DOS attack
* <p>Default value: {@code 128}</p>
*/
HTTP_MAX_PARAMS("http.params.max"),
/**
* {@code act.http.port} specifies the default http port the application
* listen to
* <p/>
* <p>Default value: {@code 5460}</p>
*/
HTTP_PORT("http.port"),
/**
* `act.http.port.external` set the external port which is used to
* construct the full url.
*
* Note act does not listen to external port directly. The recommended
* pattern is to have a front end HTTP server (e.g. nginx) to handle
* the external request and forward to act
*
* Default value: `80`
*/
HTTP_EXTERNAL_PORT("http.port.external"),
/**
* `act.http.port.external.secure` set the external secure port which is
* used to construct full url string when app is running secure mode
*
* @see #HTTP_EXTERNAL_PORT
*/
HTTP_EXTERNAL_SECURE_PORT("http.port.external.secure"),
/**
* {@code act.http.secure} specifies whether the default http port is
* running https or http.
* <p></p>
* <p>
* Default value: {@code false} when Act is running in dev mode
* or {@code true} when Act is running in prod mode
* </p>
*/
@SuppressWarnings("unchecked")
HTTP_SECURE("http.secure.enabled"),
/**
* `act.i18n.enabled` turn on/off i18n tools, e.g. {@link act.i18n.LocaleResolver}
*
* Default value: `false`
*/
I18N("i18n.enabled"),
/**
* `act.i18n.locale.param_name` specifies the param name to set client locale in http request
*
* Default value: `act_locale`
*/
I18N_LOCALE_PARAM_NAME("i18n.locale.param_name"),
/**
* `act.i18n.locale.cookie_name` specifies the name for the locale cookie
*
* Default value: `act_locale`
*/
I18N_LOCALE_COOKIE_NAME("i18n.locale.cookie_name"),
/**
* {@code act.idgen.node_id.provider.impl} specifies the {@link act.util.IdGenerator.NodeIdProvider}
* implementation for {@link App#idGenerator}
* <p>Default value: {@link act.util.IdGenerator.NodeIdProvider.IpProvider}</p>
*/
ID_GEN_NODE_ID_PROVIDER("idgen.node_id.provider.impl"),
/**
* {@code act.idgen.node_id.effective_ip_bytes} specifies how many bytes in the ip address
* will be used to calculate node ID. Usually in a cluster environment, the ip address will
* be different at only (last) one byte or (last) two bytes, in which case it could set this
* configuration to {@code 1} or {@code 2}. When the configuration is set to {@code 4} then
* it means all 4 IP bytes will be used to calculate the node ID
* <p>Default value: {@code 4}</p>
*/
ID_GEN_NODE_ID_EFFECTIVE_IP_BYTES("idgen.node_id.effective_ip_bytes.size"),
/**
* {@code act.idgen.start_id.provider.impl} specifies the {@link act.util.IdGenerator.StartIdProvider}
* implementation for {@link App#idGenerator}
* <p>Default value: {@link act.util.IdGenerator.StartIdProvider.DefaultStartIdProvider}</p>
*/
ID_GEN_START_ID_PROVIDER("idgen.start_id.provider.impl"),
/**
* {@code act.idgen.start_id.file} specifies the start id persistent file for
* {@link act.util.IdGenerator.StartIdProvider.FileBasedStartCounter}
* <p>Default value: {@code .act.id-app}</p>
*/
ID_GEN_START_ID_FILE("idgen.start_id.file"),
/**
* {@code act.idgen.seq_id.provider.impl} specifies the {@link act.util.IdGenerator.SequenceProvider}
* implementation for {@link App#idGenerator}
* <p>Default value: {@link act.util.IdGenerator.SequenceProvider.AtomicLongSeq}</p>
*/
ID_GEN_SEQ_ID_PROVIDER("idgen.seq_id.provider.impl"),
/**
* {@code act.idgen.encoder.impl} specifies the {@link act.util.IdGenerator.LongEncoder}
* implementation for {@link App#idGenerator}
* <p>Default value: {@link act.util.IdGenerator.SafeLongEncoder}</p>
*/
ID_GEN_LONG_ENCODER("idgen.encoder.impl"),
/**
* {@code job.pool.size} specifies the maximum number of threads
* can exists in the application's job manager's thread pool
* <p>Default value: {@code 10}</p>
*/
JOB_POOL_SIZE("job.pool.size"),
/**
* {@code act.locale} specifies the application default locale
* <p>Default value: {@link java.util.Locale#getDefault}</p>
*/
LOCALE("locale") {
@Override
public <T> T val(Map<String, ?> configuration) {
Object o = super.val(configuration);
if (null == o) {
return null;
}
if (o instanceof String) {
return (T) Locale.forLanguageTag((String) o);
} else if (o instanceof Locale) {
return (T) o;
} else {
String s = o.toString();
return (T) Locale.forLanguageTag(s);
}
}
},
/**
* {@code act.metric.enabled}
* Turn on/off metric in Act application
*
* Default value: {@code true}
*/
METRIC_ENABLED("metric.enabled"),
/**
* {@code act.modules}
*
* Declare additional app base (for maven modules)
*
* Default value: `null`
*/
MODULES("modules"),
/**
* {@code act.namedPorts} specifies a list of port names this
* application listen to. These are additional ports other than
* the default {@link #HTTP_PORT}
* <p/>
* The list is specified as
* <pre><code>
* act.namedPorts=admin:8888;ipc:8899
* </code></pre>
* <p>Default value: {@code null}</p>
* <p>Note, the default port that specified in {@link #HTTP_PORT} configuration
* and shall not be specified in this namedPorts configuration</p>
*/
NAMED_PORTS("namedPorts"),
/**
* {@code ping.path} specify the ping path.
* If this setting is specified, then when session resolving, system
* will check if the current URL matches the setting. If matched
* then session cookie expiration time will not be changed. Otherwise
* the expiration time will refresh
* <p>Default value: {@code null}</p>
*/
PING_PATH("ping.path"),
/**
* {@code profile} specifies the profile to load configuration
* If this setting is specified, and there is a folder named as
* the {@code profile} setting sit under {@code /resource/conf}
* folder, then the properties files will be loaded from
* that folder.
* <p>Default value: the value of the {@link Act#mode()}</p>
* <p>Note, unlike other configuration items which is usually specified
* in the configuration file. {@code profile} setting is load
* by {@link System#getProperty(String)}</p>, thus it is usually
* specified with JVM argument {@code -Dprofile=<profile>}
*/
PROFILE("profile"),
/**
* `render.json.output_charset`
*
* Specifies output charset in `application/json` response header `Content-Type`
*
* Default value: `false`
*/
RENDER_JSON_OUTPUT_CHARSET("render.json.output_charset.enabled"),
/**
* `render.json.content_type.ie`
*
* Internet Explorer is know to have an issue with `application/json` content type.
* if this configuration is set, the framework will output Content-Type header using
* the setting when the request is detected as initialized from IE browser.
*
* Default value: `null`
*/
RENDER_JSON_CONTENT_TYPE_IE("render.json.content_type.ie"),
/**
* {@code resolver.error_template_path.impl} specifies error page (template)
* path resolver implementation
* <p>Default value: {@code act.util.ErrorTemplatePathResolver.DefaultErrorTemplatePathResolver}</p>
*/
RESOLVER_ERROR_TEMPLATE_PATH("resolver.error_template_path.impl"),
/**
* {@code resolver.template_path.impl} specifies the class that
* implements {@link TemplatePathResolver}. Application
* developer could use this configuration to add some flexibility to
* template path resolving logic, e.g. different home for different locale
* or different home for different device type etc.
* <p/>
* <p>Default value: {@link TemplatePathResolver}</p>
*/
RESOLVER_TEMPLATE_PATH("resolver.template_path.impl"),
/**
* `resource.preload.size.limit`
*
* Specifies the maximum number of bytes of a resource that can be preload into memory.
* Specifies `0` or negative number to disable resource preload feature
*
* Default value: `1024 * 10`, i.e. 10KB
*/
RESOURCE_PRELOAD_SIZE_LIMIT("resource.preload.size.limit"),
/**
* {@code scan_package}
* Specify the app package in which all classes is subject
* to bytecode processing, e.g enhancement and injection.
* This setting should be specified when application loaded.
* Otherwise Act will try to process all classes found in
* application's lib and classes folder, which might cause
* performance issue on loading
*/
SCAN_PACKAGE("scan_package"),
/**
* {@code secret}
* Specifies the secret key the application used to do general
* encrypt/decrypt/sign etc
* <p>Default value: {@code myawesomeapp}</p>
*/
SECRET("secret"),
/**
* {@code server.header}
* Specifies the server header to be output to the response
* <p>Default value: {@code act}</p>
*/
SERVER_HEADER("server.header"),
/**
* {@code session.ttl} specifies the session duration in seconds.
* If user failed to interact with server for amount of time that
* exceeds the setting then the session will be destroyed
*
* <p>Default value: {@code 60 * 30} i.e half an hour</p>
*/
SESSION_TTL("session.ttl"),
/**
* {@code session.persistent.enabled}
* Specify whether the system
* should treat session cookie as persistent cookie. If this setting
* is enabled, then the user's session will not be destroyed after
* browser closed.
*
* <p>Default value: {@code false}</p>
*
* See <a href="http://en.wikipedia.org/wiki/HTTP_cookie#Persistent_cookie">HTTP_cookie</a>
*/
SESSION_PERSISTENT_ENABLED("session.persistent.enabled"),
/**
* {@code session.encrypted.enabled} specify whether the system should
* encrypt the key/value pairs in the session cookie. Enable session
* encryption will greatly improve the security but with the cost
* of additional CPU usage and a little bit longer time on request
* processing.
*
* <p>Default value: {@code false}</p>
*/
SESSION_ENCRYPT_ENABLED("session.encrypt.enabled"),
/**
* `act.session.key.username` specifies the session key for username
*
* Default value: `username`
*/
SESSION_KEY_USERNAME("session.key.username"),
/**
* {@code session.mapper.impl} specify the implementation of {@link act.util.SessionMapper}
*
* <p>Default value: {@code act.util.SessionMapper.DefaultSessionMapper}</p>
*/
SESSION_MAPPER("session.mapper.impl"),
/**
* {@code session.secure.enabled} specifies whether the session cookie should
* be set as secure. Enable secure session will cause session cookie only
* effective in https connection. Literally this will enforce the web site to run
* default by https.
*
* <p>Default value: {@code true}</p>
*
* <p><b>Note</b> when {@link Act Act server} is running in {@link Act.Mode#DEV mode}
* session http only will be disabled without regarding to the {@code session.secure.enabled}
* setting</p>
*/
SESSION_SECURE("session.secure.enabled"),
/**
* {@code act.source.version} specifies the java version
* of the src code. This configuration is used only
* in dev mode.
* <p>Default value: 1.7</p>
*/
SOURCE_VERSION("source.version"),
/**
* {@code act.target.version} specifies the java version
* of the compile target code. This configuration is used only
* in dev mode.
* <p>Default value: 1.7</p>
*/
TARGET_VERSION("target.version"),
/**
* {@code template.home} specifies where the view templates resides.
* If not specified then will use the {@link View#name() view name
* in lower case} as the template home if that view is used.
* <p/>
* <p>Default value: {@code default}</p>
*/
TEMPLATE_HOME("template.home"),
/**
* `upload.file.download.enabled`
*
* Turn on/off downloader for uploading files
*
* Default value: `false`
*/
UPLOAD_FILE_DOWNLOAD("upload.file.download.enabled"),
/**
* `act.url.context` specifies the app URL context.
*
* If this configuration is specified then all route configured will
* be attached to the configured context path.
*
* Default value: `null`
*/
URL_CONTEXT("url.context"),
/**
* {@code url.login} specifies the login URL which is used
* by {@link act.util.RedirectToLoginUrl}
* <p>Default value: {@code /login}</p>
*/
URL_LOGIN("url.login"),
/**
* {@code url.login.ajax} specifies the login URL which is used
* by {@link act.util.RedirectToLoginUrl} when request is AJAX
* <p>Default value: the value of {@link #URL_LOGIN}</p>
*/
URL_LOGIN_AJAX("url.login.ajax"),
/**
* {@code act.view.default} specifies the default view solution. If there
* are multiple views registered and default view are available, then
* it will be used at priority to load the templates
* <p/>
* <p>Default value: {@code rythm}</p>
*/
VIEW_DEFAULT("view.default"),
X_FORWARD_PROTOCOL("x_forward_protocol"),
;
private String key;
private Object defVal;
static ConfigKeyHelper helper = new ConfigKeyHelper(Act.F.MODE_ACCESSOR);
AppConfigKey(String key) {
this(key, null);
}
AppConfigKey(String key, Object defVal) {
this.key = key;
this.defVal = defVal;
}
public static void onApp(final App app) {
helper.classLoaderProvider(new $.F0<ClassLoader>() {
@Override
public ClassLoader apply() throws NotAppliedException, $.Break {
return app.classLoader();
}
});
}
/**
* Return the key string
*
* @return the key of the configuration
*/
public String key() {
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.
*
* @param configuration
* @return return the default value
*/
protected Object getDefVal(Map<String, ?> configuration) {
return defVal;
}
/**
* Calling to this method is equals to calling {@link #key()}
*
* @return key of the configuration
*/
@Override
public String toString() {
return key;
}
@Override
public Object defVal() {
return defVal;
}
public <T> List<T> implList(String key, Map<String, ?> configuration, Class<T> c) {
return helper.getImplList(key, configuration, c);
}
/**
* Return configuration value from the configuration data map using the {@link #key}
* of this {@link AppConfigKey setting} instance
*
* @param configuration
* @param <T>
* @return return the configuration
*/
public <T> T val(Map<String, ?> configuration) {
return helper.getConfiguration(this, configuration);
}
private static Map<String, AppConfigKey> lookup = new HashMap<String, AppConfigKey>(50);
static {
for (AppConfigKey k : values()) {
lookup.put(k.key().toLowerCase(), k);
}
}
/**
* Return key enum instance from the string in case insensitive mode
*
* @param s
* @return configuration key from the string
*/
public static AppConfigKey valueOfIgnoreCase(String s) {
E.illegalArgumentIf(S.blank(s), "config key cannot be empty");
return lookup.get(s.trim().toLowerCase());
}
}