Introduction
Plexus interpolator is the outgrowth of multiple iterations of development focused on providing a more modular, flexible interpolation framework for the expression language style commonly seen in Maven, Plexus, and other related projects.
It has its foundation in the org.codehaus.plexus.utils.interpolation
package within plexus-utils
, but has been separated in order to allow these two libraries to vary independently of one another.
Features
- Stackable Expression-Resolution Strategies
Expression-resolution strategies can be 'stacked' to provide an order of operations, containing multiple approaches that could potentially resolve a given expression.
These strategies are called
ValueSource
s, and each implements a very simple piece of resolution logic.It's also possible to define your own, domain-specific value source.
- Flexible Expression-Cycle Detection
Expression cycles are detected using various strategies, ranging from simplistic consultation of a stack of explicit in-process expressions, to tracking of in-process expressions that takes multiple synonym expression variants into account.
It's even possible to define your own
RecursionInterceptor
to implement an alternative strategy. - Configurable Regular Expression-Based Default Interpolator
The default interpolator implementation uses regular expressions to search for interpolation candidate expressions within an input string.
This interpolator can use a custom prefix/suffix pair that will effectively redefine the regular expression used to extract candidate expressions.
- Built-In Synonym Support for Expressions
Any
ValueSource
implementation can be wrapped to allow multiple synonym expressions using different expression prefixes. - Resolution Feedback
ValueSource
implementations have the option of implementingFeedbackEnabledValueSource
, which provides the ability to give feedback to the calling code about what failed during expression resolution. For instance, theObjectBasedValueSource
traverses the object graph below a given root object; if an object in that graph doesn't contain a property corresponding to the expression-part currently being navigated, the value source can store a feedback message to that effect. Once interpolation of the larger input string has completed, the calling code can use theInterpolator.getFeedback()
method to retrieve this feedback message (among others).
Getting Started
The simplest way to explain how to use the plexus-interpolation API is with a few examples.
First, let's look at a simplified version of the interpolation configuration used in Maven. Remember that Maven uses several source for interpolation of its POM files: the POM itself, system properties, user-defined properties, and environment variables from the shell that spawned the current Java process. Also, Maven allows POM references to be defined as ${pom.groupId}, ${project.groupId}, or even the discouraged ${groupId}.
The following is a simplified version of the plexus-interpolation configuration Maven might use to resolve POM expressions:
// serialize current POM object graph into a string called serializedPOM. RegexBasedInterpolator interpolator = new RegexBasedInterpolator(); interpolator.addValueSource( new EnvarBasedValueSource() ); interpolator.addValueSource( new PropertiesBasedValueSource( systemProperties ) ); List<String> synonymPrefixes = new ArrayList<String>(); synonymPrefixes.add( "project." ); synonymPrefixes.add( "pom." ); PrefixedValueSourceWrapper modelWrapper = new PrefixedValueSourceWrapper( synonymPrefixes, new ObjectBasedValueSource( pomModel ), true ); interpolator.addValueSource( modelWrapper ); PrefixedValueSourceWrapper pomPropertyWrapper = new PrefixedValueSourceWrapper( synonymPrefixes, new PropertiesBasedValueSource( pomModel.getProperties() ), true ); interpolator.addValueSource( pomPropertyWrapper ); interpolator.addValueSource( new PropertyBasedValueSource( userDefinedProperties ) ); RecursionInterceptor recursionInterceptor = new PrefixAwareRecursionInterceptor( synonymPrefixes, true ); serializedPOM = interpolator.interpolate( serializedPOM, recursionInterceptor ); // parse POM back into an object graph, and pass it back.