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:45 UTC

[archiva-components] branch master updated (768ab52 -> a054f7b)

This is an automated email from the ASF dual-hosted git repository.

martin_s pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/archiva-components.git.


    from 768ab52  Initial commit. Consolidation of redback components into one git project.
     new 318b406  Changing module name
     new a054f7b  Adding expression evaluator

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 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 +++++
 {src => expression-evaluator/src}/site/site.xml    |  32 +--
 .../sources/DefaultExpressionEvaluatorTest.java    | 214 +++++++++++++++++++++
 pom.xml                                            |   6 +-
 11 files changed, 703 insertions(+), 30 deletions(-)
 create mode 100644 expression-evaluator/.gitignore
 create mode 100644 expression-evaluator/pom.xml
 create mode 100644 expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/DefaultExpressionEvaluator.java
 create mode 100644 expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/EvaluatorException.java
 create mode 100644 expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/ExpressionEvaluator.java
 create mode 100644 expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/ExpressionSource.java
 create mode 100644 expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/sources/PropertiesExpressionSource.java
 create mode 100644 expression-evaluator/src/main/java/org/apache/archiva/components/evaluator/sources/SystemPropertyExpressionSource.java
 copy {src => expression-evaluator/src}/site/site.xml (52%)
 create mode 100644 expression-evaluator/src/test/java/org/apache/archiva/components/evaluator/sources/DefaultExpressionEvaluatorTest.java


[archiva-components] 01/02: Changing module name

Posted by ma...@apache.org.
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 318b4060e5c6aa58aca44fe661a8786dc24e505e
Author: Martin Stockhammer <ma...@apache.org>
AuthorDate: Thu Oct 17 11:19:23 2019 +0200

    Changing module name
---
 pom.xml | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 1385167..281081f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
   <artifactId>archiva-components</artifactId>
   <version>3.0-SNAPSHOT</version>
   <packaging>pom</packaging>
-  <name>Apache Archiva Components</name>
+  <name>Archiva Components :: Parent</name>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -44,6 +44,10 @@
 
   <description>Parent Pom for various components used in Apache Archiva and Redback.</description>
 
+  <modules>
+    <module>expression-evaluator</module>
+  </modules> 
+
   <scm>
     <connection>scm:git:https://github.com/apache/archiva-components.git</connection>
     <developerConnection>scm:git:https://github.com/apache/archiva-components.git</developerConnection>


[archiva-components] 02/02: Adding expression evaluator

Posted by ma...@apache.org.
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.
+        }
+    }
+}