blob: 82531592853b5588d0b05c53fc2ee94c3b4e0122 [file] [log] [blame]
<!DOCTYPE HTML>
<!--
/***************************************************************************************************************************
* 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.
*
***************************************************************************************************************************/
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
/* For viewing in Page Designer */
@IMPORT url("../../../../../../javadoc.css");
/* For viewing in REST interface */
@IMPORT url("../htdocs/javadoc.css");
body {
margin: 20px;
}
</style>
<script>
/* Replace all @code and @link tags. */
window.onload = function() {
document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>');
}
</script>
</head>
<body>
<p>Simple Variable Language</p>
<script>
function toggle(x) {
var div = x.nextSibling;
while (div != null && div.nodeType != 1)
div = div.nextSibling;
if (div != null) {
var d = div.style.display;
if (d == 'block' || d == '') {
div.style.display = 'none';
x.className += " closed";
} else {
div.style.display = 'block';
x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' );
}
}
}
</script>
<a id='TOC'></a><h5 class='toc'>Table of Contents</h5>
<ol class='toc'>
<li><p><a class='doclink' href='#SimpleVarLanguage'>Simple Variable Language</a></p>
<ol>
<li><p><a class='doclink' href='#Vars'>Vars</a></p>
<li><p><a class='doclink' href='#VarResolvers'>VarResolvers and VarResolverSessions</a></p>
<li><p><a class='doclink' href='#OtherNotes'>Other Notes</a></p>
</ol>
</li>
</ol>
<!-- ======================================================================================================== -->
<a id="SimpleVarLanguage"></a>
<h2 class='topic' onclick='toggle(this)'>1 - Simple Variable Language</h2>
<div class='topic'>
<p>
The <code>org.apache.juneau.svl</code> package defines an API for a language called "Simple Variable Language".
In a nutshell, Simple Variable Language (or SVL) is text that contains variables of the form <js>"$varName{varKey}"</js>.
</p>
<p>
Variables can be recursively nested within the varKey (e.g. <js>"$FOO{$BAR{xxx},$BAZ{xxx}}"</js>).
Variables can also return values that themselves contain more variables.
</p>
<p>
The {@link org.apache.juneau.svl.VarResolver} class is used to resolve variables.
The {@link org.apache.juneau.svl.VarResolver#DEFAULT} resolver will resolve <js>"$S{systemProperty}"</js>
and <js>"$E{envVariable}"</js> variables.
</p>
<p class='bcode'>
<jc>// Use the default variable resolver to resolve a string that contains $S (system property) variables</jc>
String myProperty = VarResolver.<jsf>DEFAULT</jsf>.resolve(<js>"The Java home directory is $S{java.home}"</js>);
</p>
<p>
The following shows how variables can be arbitrarily nested...
</p>
<p class='bcode'>
<jc>// Look up a property in the following order:
// 1) MYPROPERTY environment variable.
// 2) 'my.property' system property if environment variable not found.
// 3) 'not found' string if system property not found.</jc>
String myproperty = VarResolver.<jsf>DEFAULT</jsf>.resolve(<js>"$E{MYPROPERTY,$S{my.property,not found}}"</js>);
</p>
<!-- ======================================================================================================== -->
<a id="Vars"></a>
<h3 class='topic' onclick='toggle(this)'>1.1 - Vars</h3>
<div class='topic'>
<p>
Variables are defined through the {@link org.apache.juneau.svl.Var} API.
</p>
<p class='bcode'>
<jc>// Create a var resolver that extends the default resolver and appends our own "$URLEncode{...}" variable</jc>
<jc>// First create our var.</jc>
<jk>public class</jk> UrlEncodeVar <jk>extends</jk> SimpleVar {
<jc>// Must have a no-arg constructor!</jc>
<jk>public</jk> UrlEncodeVar() {
<jk>super</jk>(<js>"URLEncode"</js>);
}
<jc>// The method we must implement</jc>
<ja>@Override</ja>
<jk>public</jk> String resolve(VarResolverSession session, String varVal) {
<jk>return</jk> URLEncoder.<jsm>encode</jsm>(varVal, <js>"UTF-8"</js>);
}
}
<jc>// Next create a var resolver that extends the existing DEFAULT resolver
// that supports resolving system properties.</jc>
VarResolver r = VarResolver.<jsf>DEFAULT</jsf>.builder().vars(UrlEncodeVar.<jk>class</jk>).build();
<jc>// Retrieve a system property and URL-encode it if necessary.</jc>
String myProperty = r.resolve(<js>"$URLEncode{$S{my.property}}"</js>);
</p>
<p>
The following shows the class hierarchy of the {@link org.apache.juneau.svl.Var} class and all current
predefined implementations.
</p>
<ul class='doctree'>
<li class='jac'>
{@link org.apache.juneau.svl.Var}
- Superclass of all vars.
<ul>
<li class='jac'>
{@link org.apache.juneau.svl.SimpleVar}
- Superclass of all vars that return strings.
<ul>
<li class='jac'>
{@link org.apache.juneau.svl.DefaultingVar}
- Variables that define a default value if the resolve method returns null.
<ul>
<li class='jac'>
{@link org.apache.juneau.svl.MapVar}
- Variables that pull values from maps.
<ul>
<li class='jc'>
{@link org.apache.juneau.svl.vars.SystemPropertiesVar}
- Resolves system properties.
</ul>
</li>
<li class='jc'>
{@link org.apache.juneau.svl.vars.ArgsVar}
- Resolves variables from an {@link org.apache.juneau.utils.Args} object.
<li class='jc'>
<code>ConfigFileVar</code>
- Resolves variables from a {@link org.apache.juneau.ini.ConfigFile} object.
<li class='jc'>
{@link org.apache.juneau.svl.vars.EnvVariablesVar}
- Resolves environment variables.
<li class='jc'>
{@link org.apache.juneau.svl.vars.ManifestFileVar}
- Resolves variables from a {@link org.apache.juneau.utils.ManifestFile} object.
<li class='jc'>
{@link org.apache.juneau.rest.vars.ServletInitParamVar}
- Resolves servlet initialization parameters.
</ul>
</li>
<li class='jac'>
{@link org.apache.juneau.svl.MultipartVar}
- Variables that consist of 2 or more comma-delimited arguments.
<ul>
<li class='jc'>
{@link org.apache.juneau.rest.vars.LocalizationVar}
- Resolves localized strings for an HTTP request.
</ul>
</li>
<li class='jc'>
{@link org.apache.juneau.rest.vars.RequestVar}
- Resolves specialized HTTP request values.
<li class='jc'>
{@link org.apache.juneau.rest.vars.UrlEncodeVar}
- URL-encodes the value inside the variable.
</ul>
</li>
<li class='jac'>
{@link org.apache.juneau.svl.StreamedVar}
- Superclass of all vars that stream their value to writers.
<ul>
<li class='jc'>
{@link org.apache.juneau.rest.vars.SerializedRequestAttrVar}
- Resolves HTTP request attribute values passed through a
{@link org.apache.juneau.serializer.Serializer}.
</ul>
</li>
</ul>
</li>
</ul>
</div>
<!-- ======================================================================================================== -->
<a id="VarResolvers"></a>
<h3 class='topic' onclick='toggle(this)'>1.2 - VarResolvers and VarResolverSessions</h3>
<div class='topic'>
<p>
The main class for performing variable resolution is {@link org.apache.juneau.svl.VarResolver}.
Two methods are provided for resolving variables:
</p>
<ul class='doctree'>
<li class='jm'>
{@link org.apache.juneau.svl.VarResolver#resolve(String)}
- Resolves variables and returns the results as a simple string.
<li class='jm'>
{@link org.apache.juneau.svl.VarResolver#resolveTo(String,Writer)}
- Resolves variables and sends results to a writer.
</ul>
<p>
Var resolvers can have zero or more context objects associated with them.
Some {@link org.apache.juneau.svl.Var Vars} rely on the existence of some other object, such as an
{@link org.apache.juneau.utils.Args} object
for {@link org.apache.juneau.svl.vars.ArgsVar} or a {@link org.apache.juneau.ini.ConfigFile} for a
<code>ConfigFileVar</code>.
These object dependencies are made by setting context objects on the var resolver.
</p>
<p>
Context objects are set through the {@link org.apache.juneau.svl.VarResolverBuilder
#contextObject(String,Object)} method.
They can be any class type.
</p>
<p>
Context objects are used by {@link org.apache.juneau.svl.Var Vars} by calling the
{@link org.apache.juneau.svl.VarResolverSession#getSessionObject(Class, String)} method.
</p>
<p>
In addition to context objects, there are also session objects.
Session objects are considered more ephemeral than context objects.
While a context object is unlikely to ever change, a session object may change on every use of the var
resolver.
For example, the server API defines various <code>Var</code> objects that use the <code>RestRequest</code>
object as a session object for the duration of a single HTTP request.
</p>
<p>
Session objects are used by calling the {@link org.apache.juneau.svl.VarResolver#createSession()} or
{@link org.apache.juneau.svl.VarResolver#createSession(Map)} methods to create an instance of a
{@link org.apache.juneau.svl.VarResolverSession} object that contains
{@link org.apache.juneau.svl.VarResolverSession#resolve(String)} and
{@link org.apache.juneau.svl.VarResolverSession#resolveTo(String,Writer)} methods that are identical to
{@link org.apache.juneau.svl.VarResolver#resolve(String)} and
{@link org.apache.juneau.svl.VarResolver#resolveTo(String, Writer)} except that the <code>Var</code> objects
have access to the session objects through the
{@link org.apache.juneau.svl.VarResolverSession#getSessionObject(Class, String)} method.
Session objects are specified through either the {@link org.apache.juneau.svl.VarResolver#createSession(Map)}
method or the {@link org.apache.juneau.svl.VarResolverSession#sessionObject(String, Object)} methods.
</p>
<p>
Like Context object, Session objects are used by {@link org.apache.juneau.svl.Var Vars} by calling the
{@link org.apache.juneau.svl.VarResolverSession#getSessionObject(Class, String)} method.
</p>
<p>
Var resolvers can be cloned and extended by using the {@link org.apache.juneau.svl.VarResolver#builder()}
method.
Cloning a resolver will copy it's {@link org.apache.juneau.svl.Var} class names and context objects.
</p>
<h6 class='topic'>Example:</h6>
<p class='bcode'>
<jc>// Create a resolver that copies the default resolver and adds $C and $ARG vars.</jc>
VarResolver myVarResolver = VarResolver.<jsf>DEFAULT</jsf>.builder().vars(ConfigFileVar.<jk>class</jk>,
ArgsVar.<jk>class</jk>).build();
</p>
</div>
<!-- ======================================================================================================== -->
<a id="OtherNotes"></a>
<h3 class='topic' onclick='toggle(this)'>1.3 - Other Notes</h3>
<div class='topic'>
<ul class='spaced-list'>
<li>
The escape character <js>'\'</js> can be used when necessary to escape the following characters:
<code>$ , { }</code>
<li>
<b>WARNING:</b> It is possible to cause {@link java.lang.StackOverflowError StackOverflowErrors} if
your nested variables result in a recursive loop (e.g. the environment variable
<code>'MYPROPERTY'</code> has the value <code>'$E{MYPROPERTY}'</code>).
So don't do that!
<li>
As a general rule, this class tries to be as efficient as possible by not creating new strings when not
needed.
<br>For example, calling the resolve method on a string that doesn't contain variables (e.g.
<code>resolver.resolve(<js>"foobar"</js>)</code>) will simply be a no-op and return the same string.
</ul>
</div>
</div>
</body>
</html>