org.apache.maven.project.interpolation.RegexBasedModelInterpolator Maven / Gradle / Ivy
Go to download
This library is used to not only read Maven project object model files, but to assemble inheritence
and to retrieve remote models as required.
package org.apache.maven.project.interpolation;
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* 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.
*/
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.introspection.ReflectionValueExtractor;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
/**
* Use a regular expression search to find and resolve expressions within the POM.
*
* @author jdcasey Created on Feb 3, 2005
* @version $Id: RegexBasedModelInterpolator.java 291735 2005-09-26 20:29:20Z jdcasey $
* @todo Consolidate this logic with the PluginParameterExpressionEvaluator, minus deprecations/bans.
*/
public class RegexBasedModelInterpolator
extends AbstractLogEnabled
implements ModelInterpolator
{
private static final Pattern EXPRESSION_PATTERN = Pattern.compile( "\\$\\{(pom\\.|project\\.)?([^}]+)\\}" );
/**
* Serialize the inbound Model instance to a StringWriter, perform the regex replacement to resolve
* POM expressions, then re-parse into the resolved Model instance.
*
* NOTE: This will result in a different instance of Model being returned!!!
*
* @param model The inbound Model instance, to serialize and reference for expression resolution
* @param context The other context map to be used during resolution
* @return The resolved instance of the inbound Model. This is a different instance!
*/
public Model interpolate( Model model, Map context )
throws ModelInterpolationException
{
StringWriter sWriter = new StringWriter();
MavenXpp3Writer writer = new MavenXpp3Writer();
try
{
writer.write( sWriter, model );
}
catch ( IOException e )
{
throw new ModelInterpolationException( "Cannot serialize project model for interpolation.", e );
}
String serializedModel = sWriter.toString();
serializedModel = interpolateInternal( serializedModel, model, context );
StringReader sReader = new StringReader( serializedModel );
MavenXpp3Reader modelReader = new MavenXpp3Reader();
try
{
model = modelReader.read( sReader );
}
catch ( IOException e )
{
throw new ModelInterpolationException(
"Cannot read project model from interpolating filter of serialized version.", e );
}
catch ( XmlPullParserException e )
{
throw new ModelInterpolationException(
"Cannot read project model from interpolating filter of serialized version.", e );
}
return model;
}
private String interpolateInternal( String src, Model model, Map context )
throws ModelInterpolationException
{
String result = src;
Matcher matcher = EXPRESSION_PATTERN.matcher( result );
while ( matcher.find() )
{
String wholeExpr = matcher.group( 0 );
String realExpr = matcher.group( 2 );
Object value = context.get( realExpr );
if ( value == null )
{
value = model.getProperties().getProperty( realExpr );
}
try
{
if ( value == null )
{
value = ReflectionValueExtractor.evaluate( realExpr, model );
}
}
catch ( Exception e )
{
Logger logger = getLogger();
if ( logger != null )
{
logger.debug( "POM interpolation cannot proceed with expression: " + wholeExpr + ". Skipping...",
e );
}
}
// if the expression refers to itself, skip it.
if ( wholeExpr.equals( value ) )
{
throw new ModelInterpolationException( wholeExpr, model.getId() + " references itself." );
}
if ( value != null )
{
result = StringUtils.replace( result, wholeExpr, String.valueOf( value ) );
// could use:
// result = matcher.replaceFirst( stringValue );
// but this could result in multiple lookups of stringValue, and replaceAll is not correct behaviour
matcher.reset( result );
}
}
return result;
}
}