remove plexus naming prefix
git-svn-id: https://svn.apache.org/repos/asf/archiva/redback/redback-components/trunk@1327299 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..3d16462
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.archiva.redback.components</groupId>
+ <artifactId>redback-components</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <relativePath>../redback-components-parent/pom.xml</relativePath>
+ </parent>
+ <artifactId>plexus-expression-evaluator</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <name>Plexus Expression Evaluator Components</name>
+ <packaging>jar</packaging>
+
+ <url>http://archiva.apache.org/redback/components/${project.artifactId}</url>
+
+ <distributionManagement>
+ <site>
+ <id>apache.website</id>
+ <url>scp://people.apache.org/www/archiva.apache.org/redback/components/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/archiva/redback/redback-components/trunk/plexus-expression-evaluator</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/archiva/redback/redback-components/trunk/plexus-expression-evaluator</developerConnection>
+ <url>http://svn.apache.org/viewvc/archiva/redback/redback-components/trunk/plexus-expression-evaluator</url>
+ </scm>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>1.5.6</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/src/main/java/org/codehaus/plexus/evaluator/DefaultExpressionEvaluator.java b/src/main/java/org/codehaus/plexus/evaluator/DefaultExpressionEvaluator.java
new file mode 100644
index 0000000..ad3a5e5
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/evaluator/DefaultExpressionEvaluator.java
@@ -0,0 +1,162 @@
+package org.codehaus.plexus.evaluator;
+
+/*
+ * 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.
+ */
+
+import org.codehaus.plexus.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * DefaultExpressionEvaluator
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ * @plexus.component role="org.codehaus.plexus.evaluator.ExpressionEvaluator"
+ * role-hint="default"
+ * instantiation-strategy="per-lookup"
+ */
+public class DefaultExpressionEvaluator
+ implements ExpressionEvaluator
+{
+ private List expressionSources;
+
+ public DefaultExpressionEvaluator()
+ {
+ expressionSources = new ArrayList();
+ }
+
+ public void addExpressionSource( ExpressionSource source )
+ {
+ expressionSources.add( source );
+ }
+
+ public String expand( String str )
+ throws EvaluatorException
+ {
+ return recursiveExpand( str, new ArrayList() );
+ }
+
+ private String recursiveExpand( String str, List seenExpressions )
+ throws EvaluatorException
+ {
+ if ( StringUtils.isEmpty( str ) )
+ {
+ // Empty string. Fail fast.
+ return str;
+ }
+
+ if ( str.indexOf( "${" ) < 0 )
+ {
+ // Contains no potential expressions. Fail fast.
+ return str;
+ }
+
+ if ( this.expressionSources.isEmpty() )
+ {
+ throw new EvaluatorException( "Unable to expand expressions with empty ExpressionSource list." );
+ }
+
+ Pattern pat = Pattern.compile( "(?<=[^$]|^)(\\$\\{[^}]*\\})" );
+ Matcher mat = pat.matcher( str );
+ int offset = 0;
+ String expression;
+ String value;
+ StringBuffer expanded = new StringBuffer();
+
+ while ( mat.find( offset ) )
+ {
+ expression = mat.group( 1 );
+
+ if ( seenExpressions.contains( expression ) )
+ {
+ throw new EvaluatorException( "A recursive cycle has been detected with expression " + expression + "." );
+ }
+
+ seenExpressions.add( expression );
+
+ expanded.append( str.substring( offset, mat.start( 1 ) ) );
+ value = findValue( expression );
+ if ( value != null )
+ {
+ String resolvedValue = recursiveExpand( value, seenExpressions );
+ expanded.append( resolvedValue );
+ }
+ else
+ {
+ expanded.append( expression );
+ }
+ offset = mat.end( 1 );
+ }
+
+ expanded.append( str.substring( offset ) );
+
+ if ( expanded.indexOf( "$$" ) >= 0 )
+ {
+ // Special case for escaped content.
+ return expanded.toString().replaceAll( "\\$\\$", "\\$" );
+ }
+ else
+ {
+ // return expanded
+ return expanded.toString();
+ }
+ }
+
+ private String findValue( String expression )
+ {
+ String newExpression = expression.trim();
+ if ( newExpression.startsWith( "${" ) && newExpression.endsWith( "}" ) )
+ {
+ newExpression = newExpression.substring( 2, newExpression.length() - 1 );
+ }
+
+ if ( StringUtils.isEmpty( newExpression ) )
+ {
+ return null;
+ }
+
+ String value = null;
+ Iterator it = this.expressionSources.iterator();
+ while ( it.hasNext() )
+ {
+ ExpressionSource source = (ExpressionSource) it.next();
+ value = source.getExpressionValue( newExpression );
+ if ( value != null )
+ {
+ return value;
+ }
+ }
+ return null;
+ }
+
+ public List getExpressionSourceList()
+ {
+ return this.expressionSources;
+ }
+
+ public boolean removeExpressionSource( ExpressionSource source )
+ {
+ return this.expressionSources.remove( source );
+ }
+}
diff --git a/src/main/java/org/codehaus/plexus/evaluator/EvaluatorException.java b/src/main/java/org/codehaus/plexus/evaluator/EvaluatorException.java
new file mode 100644
index 0000000..8cade66
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/evaluator/EvaluatorException.java
@@ -0,0 +1,50 @@
+package org.codehaus.plexus.evaluator;
+
+/*
+ * 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.
+ */
+
+/**
+ * EvaluatorException
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class EvaluatorException
+ extends Exception
+{
+ public EvaluatorException()
+ {
+ super();
+ }
+
+ public EvaluatorException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public EvaluatorException( String message )
+ {
+ super( message );
+ }
+
+ public EvaluatorException( Throwable cause )
+ {
+ super( cause );
+ }
+}
diff --git a/src/main/java/org/codehaus/plexus/evaluator/ExpressionEvaluator.java b/src/main/java/org/codehaus/plexus/evaluator/ExpressionEvaluator.java
new file mode 100644
index 0000000..5b38f72
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/evaluator/ExpressionEvaluator.java
@@ -0,0 +1,65 @@
+package org.codehaus.plexus.evaluator;
+
+/*
+ * 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.
+ */
+
+import java.util.List;
+
+/**
+ * ExpressionEvaluator
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public interface ExpressionEvaluator
+{
+ String ROLE = ExpressionEvaluator.class.getName();
+
+ /**
+ * Add a source for expression resolution.
+ *
+ * @param source the source to add.
+ */
+ void addExpressionSource( ExpressionSource source );
+
+ /**
+ * Evaluate a string, and expand expressions as needed.
+ *
+ * @param str the expression
+ * @return the value of the expression
+ * @throws EvaluatorException if a problem occurs whilst evaluating
+ */
+ String expand( String str )
+ throws EvaluatorException;
+
+ /**
+ * Get the List of expression sources.
+ *
+ * @return the list of expression sources.
+ */
+ List getExpressionSourceList();
+
+ /**
+ * Remove a specific expression source.
+ *
+ * @param source the source to remove.
+ * @return true if expression source was removed.
+ */
+ boolean removeExpressionSource( ExpressionSource source );
+}
diff --git a/src/main/java/org/codehaus/plexus/evaluator/ExpressionSource.java b/src/main/java/org/codehaus/plexus/evaluator/ExpressionSource.java
new file mode 100644
index 0000000..55a538e
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/evaluator/ExpressionSource.java
@@ -0,0 +1,37 @@
+package org.codehaus.plexus.evaluator;
+
+/*
+ * 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.
+ */
+
+/**
+ * ExpressionSource
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public interface ExpressionSource
+{
+ /**
+ * Gets a value for a provided Expression.
+ *
+ * @param expression the expression to attempt to get a value for.
+ * @return the value for the expression, or null if no value found.
+ */
+ String getExpressionValue( String expression );
+}
diff --git a/src/main/java/org/codehaus/plexus/evaluator/sources/PropertiesExpressionSource.java b/src/main/java/org/codehaus/plexus/evaluator/sources/PropertiesExpressionSource.java
new file mode 100644
index 0000000..9cd1387
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/evaluator/sources/PropertiesExpressionSource.java
@@ -0,0 +1,67 @@
+package org.codehaus.plexus.evaluator.sources;
+
+/*
+ * 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.
+ */
+
+import org.codehaus.plexus.evaluator.ExpressionSource;
+
+import java.util.Properties;
+
+/**
+ * PropertiesExpressionSource
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.codehaus.plexus.evaluator.ExpressionSource"
+ * role-hint="properties"
+ */
+public class PropertiesExpressionSource
+ implements ExpressionSource
+{
+ private Properties properties;
+
+ public String getExpressionValue( String expression )
+ {
+ if ( properties == null )
+ {
+ throw new IllegalStateException( "Properties object has not been initialized." );
+ }
+
+ try
+ {
+ return properties.getProperty( expression );
+ }
+ catch ( Exception e )
+ {
+ return null;
+ }
+ }
+
+ public Properties getProperties()
+ {
+ return properties;
+ }
+
+ public void setProperties( Properties properties )
+ {
+ this.properties = properties;
+ }
+
+}
diff --git a/src/main/java/org/codehaus/plexus/evaluator/sources/SystemPropertyExpressionSource.java b/src/main/java/org/codehaus/plexus/evaluator/sources/SystemPropertyExpressionSource.java
new file mode 100644
index 0000000..ddbba84
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/evaluator/sources/SystemPropertyExpressionSource.java
@@ -0,0 +1,47 @@
+package org.codehaus.plexus.evaluator.sources;
+
+/*
+ * 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.
+ */
+
+import org.codehaus.plexus.evaluator.ExpressionSource;
+
+/**
+ * SystemPropertyExpressionSource
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.codehaus.plexus.evaluator.ExpressionSource"
+ * role-hint="sysprops"
+ */
+public class SystemPropertyExpressionSource
+ implements ExpressionSource
+{
+ public String getExpressionValue( String expression )
+ {
+ try
+ {
+ return System.getProperty( expression );
+ }
+ catch ( Exception e )
+ {
+ return null;
+ }
+ }
+}
diff --git a/src/test/java/org/codehaus/plexus/evaluator/sources/DefaultExpressionEvaluatorTest.java b/src/test/java/org/codehaus/plexus/evaluator/sources/DefaultExpressionEvaluatorTest.java
new file mode 100644
index 0000000..c6d15e2
--- /dev/null
+++ b/src/test/java/org/codehaus/plexus/evaluator/sources/DefaultExpressionEvaluatorTest.java
@@ -0,0 +1,212 @@
+package org.codehaus.plexus.evaluator.sources;
+
+/*
+ * 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.
+ */
+
+import junit.framework.TestCase;
+import org.codehaus.plexus.evaluator.DefaultExpressionEvaluator;
+import org.codehaus.plexus.evaluator.EvaluatorException;
+import org.codehaus.plexus.evaluator.ExpressionEvaluator;
+
+import java.util.Properties;
+
+/**
+ * DefaultExpressionEvaluatorTest
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class DefaultExpressionEvaluatorTest
+ extends TestCase
+{
+ private ExpressionEvaluator evaluator;
+
+ protected void setUp()
+ throws Exception
+ {
+ super.setUp();
+
+ evaluator = new DefaultExpressionEvaluator();
+ }
+
+ public void testSimple()
+ throws EvaluatorException
+ {
+ Properties props = new Properties();
+ props.setProperty( "fruit", "apple" );
+
+ PropertiesExpressionSource propsSource = new PropertiesExpressionSource();
+ propsSource.setProperties( props );
+ evaluator.addExpressionSource( propsSource );
+
+ String expression = "${fruit}";
+ String expected = "apple";
+
+ String actual = evaluator.expand( expression );
+ assertEquals( expected, actual );
+ }
+
+ public void testSimpleStartOfLine()
+ throws EvaluatorException
+ {
+ Properties props = new Properties();
+ props.setProperty( "fruit", "apple" );
+
+ PropertiesExpressionSource propsSource = new PropertiesExpressionSource();
+ propsSource.setProperties( props );
+ evaluator.addExpressionSource( propsSource );
+
+ String expression = "${fruit} is good for you.";
+ String expected = "apple is good for you.";
+
+ String actual = evaluator.expand( expression );
+ assertEquals( expected, actual );
+ }
+
+ public void testSimpleEndOfLine()
+ throws EvaluatorException
+ {
+ Properties props = new Properties();
+ props.setProperty( "fruit", "apple" );
+
+ PropertiesExpressionSource propsSource = new PropertiesExpressionSource();
+ propsSource.setProperties( props );
+ evaluator.addExpressionSource( propsSource );
+
+ String expression = "watch out for the worm in the ${fruit}";
+ String expected = "watch out for the worm in the apple";
+
+ String actual = evaluator.expand( expression );
+ assertEquals( expected, actual );
+ }
+
+ public void testSimpleSystemProperty()
+ throws EvaluatorException
+ {
+ evaluator.addExpressionSource( new SystemPropertyExpressionSource() );
+
+ String userHome = System.getProperty( "user.home" );
+ String expression = "My HOME directory is ${user.home}";
+ String expected = "My HOME directory is " + userHome;
+
+ String actual = evaluator.expand( expression );
+ assertEquals( expected, actual );
+ }
+
+ public void testMultiExpression()
+ throws EvaluatorException
+ {
+ evaluator.addExpressionSource( new SystemPropertyExpressionSource() );
+
+ String userName = System.getProperty( "user.name" );
+ String userHome = System.getProperty( "user.home" );
+ String expression = "${user.name}'s home directory is ${user.home}";
+ String expected = userName + "'s home directory is " + userHome;
+
+ String actual = evaluator.expand( expression );
+ assertEquals( expected, actual );
+ }
+
+ /**
+ * This use case was discovered by a user of archiva.
+ * The last expression doesn't get evaluated properly.
+ * <p/>
+ * The result (with the bug) was "2.0.4${prj.ver.suf}"
+ */
+ public void testMultiExpressionVersionBug()
+ throws EvaluatorException
+ {
+ Properties props = new Properties();
+ props.setProperty( "prj.ver.maj", "2" );
+ props.setProperty( "prj.ver.min", "0" );
+ props.setProperty( "prj.ver.inc", "4" );
+ props.setProperty( "prj.ver.suf", "-SNAPSHOT" );
+
+ PropertiesExpressionSource propsSource = new PropertiesExpressionSource();
+ propsSource.setProperties( props );
+ evaluator.addExpressionSource( propsSource );
+
+ String expression = "${prj.ver.maj}.${prj.ver.min}.${prj.ver.inc}${prj.ver.suf}";
+ String expected = "2.0.4-SNAPSHOT";
+
+ String actual = evaluator.expand( expression );
+ assertEquals( expected, actual );
+ }
+
+ public void testEscaping()
+ throws EvaluatorException
+ {
+ evaluator.addExpressionSource( new SystemPropertyExpressionSource() );
+
+ String userName = System.getProperty( "user.name" );
+ String userHome = System.getProperty( "user.home" );
+ String expression = "${user.name}'s home directory is ${user.home} (fetched via $${user.home} expression)";
+ String expected = userName + "'s home directory is " + userHome + " (fetched via ${user.home} expression)";
+
+ String actual = evaluator.expand( expression );
+ assertEquals( expected, actual );
+ }
+
+ public void testRecursiveSimple()
+ throws EvaluatorException
+ {
+ PropertiesExpressionSource propsource = new PropertiesExpressionSource();
+ Properties props = new Properties();
+
+ // Create intentional recursive lookup.
+ props.setProperty( "main.dir", "${target.dir}/classes" );
+ props.setProperty( "target.dir", "./target" );
+
+ propsource.setProperties( props );
+
+ evaluator.addExpressionSource( propsource );
+ evaluator.addExpressionSource( new SystemPropertyExpressionSource() );
+
+ String expression = "My classes directory is ${main.dir}";
+ String expected = "My classes directory is ./target/classes";
+
+ String actual = evaluator.expand( expression );
+ assertEquals( expected, actual );
+ }
+
+ public void testRecursiveCycle()
+ {
+ PropertiesExpressionSource propsource = new PropertiesExpressionSource();
+ Properties props = new Properties();
+
+ // Create intentional recursive lookup.
+ props.setProperty( "main.dir", "${test.dir}/target/classes" );
+ props.setProperty( "test.dir", "${main.dir}/target/test-classes" );
+
+ propsource.setProperties( props );
+
+ evaluator.addExpressionSource( propsource );
+ evaluator.addExpressionSource( new SystemPropertyExpressionSource() );
+
+ try
+ {
+ evaluator.expand( "My main dir is ${main.dir}" );
+ fail( "Should have thrown an EvaluatorException due to recursive cycle." );
+ }
+ catch ( EvaluatorException e )
+ {
+ // Expected path.
+ }
+ }
+}