You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ma...@apache.org on 2019/10/17 09:59:47 UTC
[archiva-components] 02/02: Adding expression evaluator
This is an automated email from the ASF dual-hosted git repository.
martin_s pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/archiva-components.git
commit a054f7b9f952158da70fadd94eda448e36c0dc13
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Thu Oct 17 11:58:20 2019 +0200
Adding expression evaluator
---
expression-evaluator/.gitignore | 10 +
expression-evaluator/pom.xml | 53 +++++
.../evaluator/DefaultExpressionEvaluator.java | 159 +++++++++++++++
.../components/evaluator/EvaluatorException.java | 50 +++++
.../components/evaluator/ExpressionEvaluator.java | 63 ++++++
.../components/evaluator/ExpressionSource.java | 37 ++++
.../sources/PropertiesExpressionSource.java | 65 +++++++
.../sources/SystemPropertyExpressionSource.java | 44 +++++
expression-evaluator/src/site/site.xml | 34 ++++
.../sources/DefaultExpressionEvaluatorTest.java | 214 +++++++++++++++++++++
10 files changed, 729 insertions(+)
diff --git a/expression-evaluator/.gitignore b/expression-evaluator/.gitignore
new file mode 100644
index 0000000..7b6772c
--- /dev/null
+++ b/expression-evaluator/.gitignore
@@ -0,0 +1,10 @@
+.idea/**
+.project
+.classpath
+.settings
+.java-version
+target
+.DS_Store
+.site-content
+out
+*.iml
diff --git a/expression-evaluator/pom.xml b/expression-evaluator/pom.xml
new file mode 100644
index 0000000..fd69415
--- /dev/null
+++ b/expression-evaluator/pom.xml
@@ -0,0 +1,53 @@
+<?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.components</groupId>
+ <artifactId>archiva-components</artifactId>
+ <version>3.0-SNAPSHOT</version>
+ </parent>
+
+ <version>3.0-SNAPSHOT</version>
+ <artifactId>archiva-components-expression-evaluator</artifactId>
+ <name>Archiva Components :: Expression Evaluator</name>
+
+ <properties>
+ <site.staging.base>${project.basedir}/..</site.staging.base>
+ </properties>
+
+
+ <url>${webUrl}/${project.artifactId}</url>
+
+ <scm>
+ <url>${scmBrowseUrl}</url>
+ </scm>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/DefaultExpressionEvaluator.java b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/DefaultExpressionEvaluator.java
new file mode 100644
index 0000000..00cfef5
--- /dev/null
+++ b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/DefaultExpressionEvaluator.java
@@ -0,0 +1,159 @@
+package org.apache.archiva.components.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.apache.commons.lang3.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>
+ *
+ */
+public class DefaultExpressionEvaluator
+ implements ExpressionEvaluator
+{
+ private List<ExpressionSource> 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<String>() );
+ }
+
+ private String recursiveExpand( String str, List<String> 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;
+ StringBuilder expanded = new StringBuilder();
+
+ 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/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/EvaluatorException.java b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/EvaluatorException.java
new file mode 100644
index 0000000..b2c68cc
--- /dev/null
+++ b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/EvaluatorException.java
@@ -0,0 +1,50 @@
+package org.apache.archiva.components.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>
+ *
+ */
+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/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/ExpressionEvaluator.java b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/ExpressionEvaluator.java
new file mode 100644
index 0000000..0aeae57
--- /dev/null
+++ b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/ExpressionEvaluator.java
@@ -0,0 +1,63 @@
+package org.apache.archiva.components.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>
+ *
+ */
+public interface ExpressionEvaluator
+{
+ /**
+ * 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/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/ExpressionSource.java b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/ExpressionSource.java
new file mode 100644
index 0000000..39d15cb
--- /dev/null
+++ b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/ExpressionSource.java
@@ -0,0 +1,37 @@
+package org.apache.archiva.components.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>
+ *
+ */
+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/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/sources/PropertiesExpressionSource.java b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/sources/PropertiesExpressionSource.java
new file mode 100644
index 0000000..4f157cb
--- /dev/null
+++ b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/sources/PropertiesExpressionSource.java
@@ -0,0 +1,65 @@
+package org.apache.archiva.components.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.apache.archiva.components.evaluator.ExpressionSource;
+
+import java.util.Properties;
+
+/**
+ * PropertiesExpressionSource
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ *
+ *
+ */
+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/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/sources/SystemPropertyExpressionSource.java b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/sources/SystemPropertyExpressionSource.java
new file mode 100644
index 0000000..522c973
--- /dev/null
+++ b/expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/sources/SystemPropertyExpressionSource.java
@@ -0,0 +1,44 @@
+package org.apache.archiva.components.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.apache.archiva.components.evaluator.ExpressionSource;
+
+/**
+ * SystemPropertyExpressionSource
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ *
+ */
+public class SystemPropertyExpressionSource
+ implements ExpressionSource
+{
+ public String getExpressionValue( String expression )
+ {
+ try
+ {
+ return System.getProperty( expression );
+ }
+ catch ( Exception e )
+ {
+ return null;
+ }
+ }
+}
diff --git a/expression-evaluator/src/site/site.xml b/expression-evaluator/src/site/site.xml
new file mode 100644
index 0000000..c3cfc21
--- /dev/null
+++ b/expression-evaluator/src/site/site.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ ~ 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 name="Expression Evaluator" >
+
+ <publishDate format="yyyy-MM-dd" position="none" />
+
+ <body>
+ <menu ref="modules" />
+ <menu ref="reports" />
+ <menu ref="ASF" />
+ <breadcrumbs>
+ <item name="Archiva Components" href="../index.html" />
+ <item name="Expression Evaluator" href="index.html" />
+ </breadcrumbs>
+ </body>
+</project>
diff --git a/expression-evaluator/src/test/java/org/apache/archiva/components/evaluator/sources/DefaultExpressionEvaluatorTest.java b/expression-evaluator/src/test/java/org/apache/archiva/components/evaluator/sources/DefaultExpressionEvaluatorTest.java
new file mode 100644
index 0000000..423ea6f
--- /dev/null
+++ b/expression-evaluator/src/test/java/org/apache/archiva/components/evaluator/sources/DefaultExpressionEvaluatorTest.java
@@ -0,0 +1,214 @@
+package org.apache.archiva.components.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.apache.archiva.components.evaluator.DefaultExpressionEvaluator;
+import org.apache.archiva.components.evaluator.EvaluatorException;
+import org.apache.archiva.components.evaluator.ExpressionEvaluator;
+import org.apache.archiva.components.evaluator.sources.PropertiesExpressionSource;
+import org.apache.archiva.components.evaluator.sources.SystemPropertyExpressionSource;
+
+import java.util.Properties;
+
+/**
+ * DefaultExpressionEvaluatorTest
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ *
+ */
+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.
+ }
+ }
+}